def build_btnpanel(self): panel = self.btnpanel = wx.Panel(self, ) panel.SetBackgroundColour(wx.Colour(*BGCOL)) btnsizer = wx.BoxSizer(wx.HORIZONTAL) self.pause_btn = wx.Button(panel, label='Pause', size=(100, 30)) self.resume_btn = wx.Button(panel, label='Resume', size=(100, 30)) self.resume_btn.Disable() self.pause_btn.Bind(wx.EVT_BUTTON, self.onPause) self.resume_btn.Bind(wx.EVT_BUTTON, self.onPause) time_label = SimpleText(panel, ' Time Range: ', minsize=(85, -1), style=LSTY) self.time_choice = MyChoice(panel, size=(120, -1), choices=('seconds', 'minutes', 'hours')) self.time_choice.SetStringSelection(self.timelabel) self.time_choice.Bind(wx.EVT_CHOICE, self.onTimeChoice) self.time_ctrl = FloatCtrl(panel, value=-self.tmin, precision=2, size=(90, -1), action=self.onDisplayTimeVal) btnsizer.Add(self.pause_btn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER, 2) btnsizer.Add(self.resume_btn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER, 2) btnsizer.Add(time_label, 1, wx.ALIGN_CENTER_HORIZONTAL, 2) btnsizer.Add(self.time_ctrl, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER, 2) btnsizer.Add(self.time_choice, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER, 2) panel.SetAutoLayout(True) panel.SetSizer(btnsizer) btnsizer.Fit(panel)
class StripChart(wx.Frame): default_colors = ((0, 0, 0), (0, 0, 255), (255, 0, 0), (0, 0, 0), (255, 0, 255), (0, 125, 0)) help_msg = """Quick help: Left-Click: to display X,Y coordinates Left-Drag: to zoom in on plot region Right-Click: display popup menu with choices: Zoom out 1 level Zoom all the way out -------------------- Configure Save Image Also, these key bindings can be used (For Mac OSX, replace 'Ctrl' with 'Apple'): Ctrl-S: save plot image to file Ctrl-C: copy plot image to clipboard Ctrl-K: Configure Plot Ctrl-Q: quit """ about_msg = """Epics PV Strip Chart version 0.1 Matt Newville <*****@*****.**> """ def __init__(self, parent=None): self.pvdata = {} self.pvlist = [' -- '] self.pvwids = [None] self.pvchoices = [None] self.colorsels = [] self.plots_drawn = [False] * 10 self.needs_refresh = False self.needs_refresh = False self.paused = False self.tmin = -60.0 self.timelabel = 'seconds' self.create_frame(parent) self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.onUpdatePlot, self.timer) self.timer.Start(POLLTIME) def create_frame(self, parent, size=(750, 450), **kwds): self.parent = parent kwds['style'] = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL kwds['size'] = size wx.Frame.__init__(self, parent, -1, 'Epics PV Strip Chart', **kwds) self.build_statusbar() self.plotpanel = PlotPanel(self, trace_color_callback=self.onTraceColor) self.plotpanel.BuildPanel() self.plotpanel.messenger = self.write_message self.build_pvpanel() self.build_btnpanel() self.build_menus() self.SetBackgroundColour(wx.Colour(*BGCOL)) mainsizer = wx.BoxSizer(wx.VERTICAL) p1 = wx.Panel(self) p1.SetBackgroundColour(wx.Colour(*BGCOL)) s1 = wx.BoxSizer(wx.HORIZONTAL) n = LabelEntry(p1, '', labeltext=' Add PV: ', size=300, action=self.onPVname) self.pvmsg = SimpleText(p1, ' ', minsize=(75, -1), style=LSTY | wx.EXPAND) s1.Add(n.label, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER, 10) s1.Add(n, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER, 10) s1.Add(self.pvmsg, 1, wx.ALIGN_LEFT | wx.ALIGN_CENTER, 10) p1.SetAutoLayout(True) p1.SetSizer(s1) s1.Fit(p1) mainsizer.Add(p1, 0, wx.GROW | wx.EXPAND, 5) mainsizer.Add( wx.StaticLine(self, size=(250, -1), style=wx.LI_HORIZONTAL), 0, wx.EXPAND | wx.GROW, 8) mainsizer.Add(self.pvpanel, 0, wx.EXPAND, 5) mainsizer.Add( wx.StaticLine(self, size=(250, -1), style=wx.LI_HORIZONTAL), 0, wx.EXPAND | wx.GROW, 8) mainsizer.Add(self.btnpanel, 0, wx.EXPAND, 5) mainsizer.Add(self.plotpanel, 1, wx.EXPAND, 5) self.SetAutoLayout(True) self.SetSizer(mainsizer) self.Fit() try: self.SetIcon(wx.Icon(ICON_FILE, wx.BITMAP_TYPE_ICO)) except: pass self.Refresh() def build_statusbar(self): sbar = self.CreateStatusBar(2, wx.CAPTION | wx.THICK_FRAME) sfont = sbar.GetFont() sfont.SetWeight(wx.BOLD) sfont.SetPointSize(10) sbar.SetFont(sfont) self.SetStatusWidths([-5, -2]) self.SetStatusText('', 0) def build_pvpanel(self): panel = self.pvpanel = wx.Panel(self) panel.SetBackgroundColour(wx.Colour(*BGCOL)) sizer = self.pvsizer = wx.GridBagSizer(4, 5) name = SimpleText(panel, ' PV: ', minsize=(75, -1), style=LSTY) colr = SimpleText(panel, ' Color ', minsize=(50, -1), style=LSTY) logs = SimpleText(panel, ' Log Scale?', minsize=(85, -1), style=LSTY) ymin = SimpleText(panel, ' Y Minimum ', minsize=(85, -1), style=LSTY) ymax = SimpleText(panel, ' Y Maximum ', minsize=(85, -1), style=LSTY) sizer.Add(name, (0, 0), (1, 1), LSTY | wx.EXPAND, 2) sizer.Add(colr, (0, 1), (1, 1), LSTY, 1) sizer.Add(logs, (0, 2), (1, 1), LSTY, 1) sizer.Add(ymin, (0, 3), (1, 1), LSTY, 1) sizer.Add(ymax, (0, 4), (1, 1), LSTY, 1) self.npv_rows = 0 for i in range(4): self.AddPV_row() panel.SetAutoLayout(True) panel.SetSizer(sizer) sizer.Fit(panel) def build_btnpanel(self): panel = self.btnpanel = wx.Panel(self, ) panel.SetBackgroundColour(wx.Colour(*BGCOL)) btnsizer = wx.BoxSizer(wx.HORIZONTAL) self.pause_btn = wx.Button(panel, label='Pause', size=(100, 30)) self.resume_btn = wx.Button(panel, label='Resume', size=(100, 30)) self.resume_btn.Disable() self.pause_btn.Bind(wx.EVT_BUTTON, self.onPause) self.resume_btn.Bind(wx.EVT_BUTTON, self.onPause) time_label = SimpleText(panel, ' Time Range: ', minsize=(85, -1), style=LSTY) self.time_choice = MyChoice(panel, size=(120, -1), choices=('seconds', 'minutes', 'hours')) self.time_choice.SetStringSelection(self.timelabel) self.time_choice.Bind(wx.EVT_CHOICE, self.onTimeChoice) self.time_ctrl = FloatCtrl(panel, value=-self.tmin, precision=2, size=(90, -1), action=self.onTimeVal) btnsizer.Add(self.pause_btn, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER, 2) btnsizer.Add(self.resume_btn, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER, 2) btnsizer.Add(time_label, 1, wx.ALIGN_CENTER_HORIZONTAL, 2) btnsizer.Add(self.time_ctrl, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER, 2) btnsizer.Add(self.time_choice, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER, 2) panel.SetAutoLayout(True) panel.SetSizer(btnsizer) btnsizer.Fit(panel) def build_menus(self): mbar = wx.MenuBar() mfile = wx.Menu() mfile.Append(MENU_SAVE_DAT, "&Save Data\tCtrl+S", "Save PNG Image of Plot") mfile.Append(MENU_SAVE_IMG, "Save Plot Image\t", "Save PNG Image of Plot") mfile.Append(MENU_CLIPB, "&Copy Image to Clipboard\tCtrl+C", "Copy Plot Image to Clipboard") mfile.AppendSeparator() mfile.Append(MENU_PSETUP, 'Page Setup...', 'Printer Setup') mfile.Append(MENU_PREVIEW, 'Print Preview...', 'Print Preview') mfile.Append(MENU_PRINT, "&Print\tCtrl+P", "Print Plot") mfile.AppendSeparator() mfile.Append(MENU_EXIT, "E&xit\tCtrl+Q", "Exit the 2D Plot Window") mopt = wx.Menu() mopt.Append(MENU_CONFIG, "Configure Plot\tCtrl+K", "Configure Plot styles, colors, labels, etc") mopt.AppendSeparator() mopt.Append(MENU_UNZOOM, "Zoom Out\tCtrl+Z", "Zoom out to full data range") mhelp = wx.Menu() mhelp.Append(MENU_HELP, "Quick Reference", "Quick Reference for MPlot") mhelp.Append(MENU_ABOUT, "About", "About MPlot") mbar.Append(mfile, "File") mbar.Append(mopt, "Options") mbar.Append(mhelp, "&Help") self.SetMenuBar(mbar) self.Bind(wx.EVT_MENU, self.onSaveData, id=MENU_SAVE_DAT) self.Bind(wx.EVT_MENU, self.onHelp, id=MENU_HELP) self.Bind(wx.EVT_MENU, self.onAbout, id=MENU_ABOUT) self.Bind(wx.EVT_MENU, self.onExit, id=MENU_EXIT) self.Bind(wx.EVT_CLOSE, self.onExit) pp = self.plotpanel self.Bind(wx.EVT_MENU, pp.configure, id=MENU_CONFIG) self.Bind(wx.EVT_MENU, pp.unzoom_all, id=MENU_UNZOOM) self.Bind(wx.EVT_MENU, pp.save_figure, id=MENU_SAVE_IMG) self.Bind(wx.EVT_MENU, pp.Print, id=MENU_PRINT) self.Bind(wx.EVT_MENU, pp.PrintSetup, id=MENU_PSETUP) self.Bind(wx.EVT_MENU, pp.PrintPreview, id=MENU_PREVIEW) self.Bind(wx.EVT_MENU, pp.canvas.Copy_to_Clipboard, id=MENU_CLIPB) def AddPV_row(self): i = self.npv_rows = self.npv_rows + 1 panel = self.pvpanel sizer = self.pvsizer pvchoice = MyChoice(panel, choices=self.pvlist, size=(200, -1)) pvchoice.SetSelection(0) logs = MyChoice(panel) logs.SetSelection(0) ymin = wx.TextCtrl(panel, -1, '', size=(75, -1)) ymax = wx.TextCtrl(panel, -1, '', size=(75, -1)) if i > 2: logs.Disable() ymin.Disable() ymax.Disable() colval = (0, 0, 0) if i < len(self.default_colors): colval = self.default_colors[i] colr = csel.ColourSelect(panel, -1, '', colval) self.colorsels.append(colr) sizer.Add(pvchoice, (i, 0), (1, 1), LSTY, 3) sizer.Add(colr, (i, 1), (1, 1), CSTY, 3) sizer.Add(logs, (i, 2), (1, 1), CSTY, 3) sizer.Add(ymin, (i, 3), (1, 1), CSTY, 3) sizer.Add(ymax, (i, 4), (1, 1), CSTY, 3) pvchoice.Bind(wx.EVT_CHOICE, Closure(self.onPVchoice, row=i)) colr.Bind(csel.EVT_COLOURSELECT, Closure(self.onPVcolor, row=i)) logs.Bind(wx.EVT_CHOICE, self.onPVwid) ymin.Bind(wx.EVT_TEXT_ENTER, self.onPVwid) ymax.Bind(wx.EVT_TEXT_ENTER, self.onPVwid) self.pvchoices.append(pvchoice) self.pvwids.append((logs, colr, ymin, ymax)) def onTraceColor(self, trace, color, **kws): irow = self.get_current_traces()[trace][0] - 1 self.colorsels[irow].SetColour(color) def onPVshow(self, event=None, row=0): if not event.IsChecked(): trace = self.plotpanel.conf.get_mpl_line(row) trace.set_data([], []) self.plotpanel.canvas.draw() self.needs_refresh = True def onPVname(self, event=None): try: name = event.GetString() except AttributeError: return self.addPV(name) @EpicsFunction def addPV(self, name): if name is not None and name not in self.pvlist: pv = PV(str(name), callback=self.onPVChange) pv.get() conn = False if pv is not None: if not pv.connected: pv.wait_for_connection() conn = pv.connected msg = 'PV not found: %s' % name if conn: msg = 'PV found: %s' % name self.pvmsg.SetLabel(msg) if not conn: return self.pvlist.append(name) self.pvdata[name] = [(time.time(), pv.get())] i_new = len(self.pvdata) new_shown = False for choice in self.pvchoices: if choice is None: continue cur = choice.GetSelection() choice.Clear() choice.SetItems(self.pvlist) choice.SetSelection(cur) if cur == 0 and not new_shown: choice.SetSelection(i_new) new_shown = True self.needs_refresh = True @DelayedEpicsCallback def onPVChange(self, pvname=None, value=None, timestamp=None, **kw): if timestamp is None: timestamp = time.time() self.pvdata[pvname].append((timestamp, value)) self.needs_refresh = True def onPVchoice(self, event=None, row=None, **kws): self.needs_refresh = True for i in range(len(self.pvlist) + 1): try: trace = self.plotpanel.conf.get_mpl_line(row - 1) trace.set_data([], []) except: pass if row == 1: self.plotpanel.set_y2label('') self.plotpanel.canvas.draw() def onPVcolor(self, event=None, row=None, **kws): self.plotpanel.conf.set_trace_color(hexcolor(event.GetValue()), trace=row - 1) self.needs_refresh = True def onPVwid(self, event=None, row=None, **kws): self.needs_refresh = True def onTimeVal(self, event=None, value=None, **kws): new = -abs(value) if abs(new) < 0.1: new = -0.1 if abs(new - self.tmin) > 1.e-3 * max(new, self.tmin): self.tmin = new self.needs_refresh = True def onTimeChoice(self, event=None, **kws): newval = event.GetString() denom, num = 1.0, 1.0 if self.timelabel != newval: if self.timelabel == 'hours': denom = 3600. elif self.timelabel == 'minutes': denom = 60.0 if newval == 'hours': num = 3600. elif newval == 'minutes': num = 60.0 self.timelabel = newval timeval = self.time_ctrl.GetValue() self.time_ctrl.SetValue(timeval * denom / num) self.plotpanel.set_xlabel('Elapsed Time (%s)' % self.timelabel) self.needs_refresh = True def onPause(self, event=None): if self.paused: self.pause_btn.Enable() self.resume_btn.Disable() else: self.pause_btn.Disable() self.resume_btn.Enable() self.paused = not self.paused def write_message(self, s, panel=0): """write a message to the Status Bar""" self.SetStatusText(s, panel) def onSaveData(self, event=None): dlg = wx.FileDialog(self, message='Save Data to File...', defaultDir=os.getcwd(), defaultFile='PVStripChart.dat', style=wx.SAVE | wx.CHANGE_DIR) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.SaveDataFiles(path) self.write_message('Saved data to %s' % path) dlg.Destroy() def SaveDataFiles(self, path): basename, ext = os.path.splitext(path) if len(ext) < 2: ext = '.dat' if ext.startswith('.'): ext = ext[1:] for pvname, data in self.pvdata.items(): tnow = time.time() tmin = data[0][0] fname = [] for s in pvname: if s not in FILECHARS: s = '_' fname.append(s) fname = os.path.join("%s_%s.%s" % (basename, ''.join(fname), ext)) buff = ["# Epics PV Strip Chart Data for PV: %s " % pvname] buff.append("# Current Time = %s " % time.ctime(tnow)) buff.append("# Earliest Time = %s " % time.ctime(tmin)) buff.append("#------------------------------") buff.append("# Timestamp Value Time-Current_Time(s)") for tx, yval in data: buff.append(" %.3f %16g %.3f" % (tx, yval, tx - tnow)) fout = open(fname, 'w') fout.write("\n".join(buff)) fout.close() #dat = tnow, func(tnow) def onAbout(self, event=None): dlg = wx.MessageDialog(self, self.about_msg, "About Epics PV Strip Chart", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def onHelp(self, event=None): dlg = wx.MessageDialog(self, self.help_msg, "Epics PV Strip Chart Help", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def onExit(self, event=None): try: self.plotpanel.win_config.Close(True) self.plotpanel.win_config.Destroy() except: pass self.Destroy() def get_current_traces(self): "return list of current traces" traces = [] # to be shown for irow, s in enumerate(self.pvchoices): if s is not None: ix = s.GetSelection() if ix > 0: name = self.pvlist[ix] logs = 1 == self.pvwids[irow][0].GetSelection() color = self.pvwids[irow][1].GetColour() ymin = get_bound(self.pvwids[irow][2].GetValue()) ymax = get_bound(self.pvwids[irow][3].GetValue()) traces.append((irow, name, logs, color, ymin, ymax)) return traces def onUpdatePlot(self, event=None): if self.paused or not self.needs_refresh: return tnow = time.time() # set timescale sec/min/hour timescale = 1.0 if self.time_choice.GetSelection() == 1: timescale = 1. / 60 elif self.time_choice.GetSelection() == 2: timescale = 1. / 3600 ylabelset, y2labelset = False, False xlabel = 'Elapsed Time (%s)' % self.timelabel itrace = -1 update_failed = False hasplot = False span1 = (1, 0) did_update = False left_axes = self.plotpanel.axes right_axes = self.plotpanel.get_right_axes() for irow, pname, uselog, color, ymin, ymax in self.get_current_traces( ): if pname not in self.pvdata: continue itrace += 1 if len(self.plots_drawn) < itrace: self.plots_drawn.extend([False] * 3) side = 'left' if itrace == 1: side = 'right' data = self.pvdata[pname][:] if len(data) < 2: update_failed = True continue tdat = timescale * (array([i[0] for i in data]) - tnow) mask = where(tdat > self.tmin) if (len(mask[0]) < 2 or ((abs(min(tdat)) / abs(1 - self.tmin)) > 0.1)): data.append((time.time(), data[0][-1])) tdat = timescale * (array([i[0] for i in data]) - tnow) mask = where(tdat > self.tmin) i0 = mask[0][0] if i0 > 0: i0 = i0 - 1 i1 = mask[0][-1] + 1 tdat = timescale * (array([i[0] for i in data[i0:i1]]) - tnow) ydat = array([i[1] for i in data[i0:i1]]) if len(ydat) < 2: update_failed = True continue if ymin is None: ymin = min(ydat) if ymax is None: ymax = max(ydat) # for more that 2 plots, scale to left hand axis if itrace == 0: span1 = (ymax - ymin, ymin) if span1[0] * ymax < 1.e-6: update_failed = True continue elif itrace > 1: yr = abs(ymax - ymin) if yr > 1.e-9: ydat = span1[1] + 0.99 * (ydat - ymin) * span1[0] / yr ymin, ymax = min(ydat), max(ydat) if self.needs_refresh: if itrace == 0: self.plotpanel.set_ylabel(pname) elif itrace == 1: self.plotpanel.set_y2label(pname) if not self.plots_drawn[itrace]: plot = self.plotpanel.oplot if itrace == 0: plot = self.plotpanel.plot try: plot(tdat, ydat, drawstyle='steps-post', side=side, ylog_scale=uselog, color=color, xmin=self.tmin, xmax=0, xlabel=xlabel, label=pname, autoscale=False) self.plots_drawn[itrace] = True except: update_failed = True else: try: self.plotpanel.update_line(itrace, tdat, ydat, draw=False) self.plotpanel.set_xylims((self.tmin, 0, ymin, ymax), side=side, autoscale=False) did_update = True except: update_failed = True axes = left_axes if itrace == 1: axes = right_axes if uselog and min(ydat) > 0: axes.set_yscale('log', basey=10) else: axes.set_yscale('linear') self.plotpanel.set_title( time.strftime("%Y-%b-%d %H:%M:%S", time.localtime())) if did_update: self.plotpanel.canvas.draw() self.needs_refresh = update_failed return
def __init__(self, parent, image_panel=None, camera_id=0, center_cb=None, xhair_cb=None, **kws): super(ConfPanel_Fly2, self).__init__(parent, center_cb=center_cb, xhair_cb=xhair_cb) self.image_panel = image_panel self.camera_id = camera_id self.camera = self.image_panel.camera wids = self.wids sizer = self.sizer self.title = self.txt("PyCapture2: ", size=285) self.title2 = self.txt(" ", size=285) sizer.Add(self.title, (0, 0), (1, 3), LEFT) sizer.Add(self.title2, (1, 0), (1, 3), LEFT) next_row = self.show_position_info(row=2) self.__initializing = True i = next_row + 1 #('Sharpness', '%', 100), ('Hue', 'deg', 100), ('Saturation', '%', 100), for dat in ( ('shutter', 'ms', 50, 0, 70), ('gain', 'dB', 0, -2, 24), # ('brightness', '%', 0, 0, 6), ('gamma', '', 1, 0.5, 4)): key, units, defval, minval, maxval = dat wids[key] = FloatCtrl(self, value=defval, minval=minval, maxval=maxval, precision=1, action=self.onValue, act_on_losefocus=True, action_kw={'prop': key}, size=(75, -1)) label = '%s' % (key.title()) if len(units) > 0: label = '%s (%s)' % (key.title(), units) sizer.Add(self.txt(label), (i, 0), (1, 1), LEFT) sizer.Add(wids[key], (i, 1), (1, 1), LEFT) akey = '%s_auto' % key wids[akey] = wx.CheckBox(self, -1, label='auto') wids[akey].SetValue(0) wids[akey].Bind(wx.EVT_CHECKBOX, Closure(self.onAuto, prop=key)) sizer.Add(wids[akey], (i, 2), (1, 1), LEFT) i = i + 1 for color in ('blue', 'red'): key = 'wb_%s' % color wids[key] = FloatCtrl(self, value=0, maxval=1024, precision=0, action=self.onValue, act_on_losefocus=True, action_kw={'prop': key}, size=(75, -1)) label = 'White Balance (%s)' % (color) sizer.Add(self.txt(label), (i, 0), (1, 1), LEFT) sizer.Add(wids[key], (i, 1), (1, 1), LEFT) if color == 'blue': akey = 'wb_auto' wids[akey] = wx.CheckBox(self, -1, label='auto') wids[akey].SetValue(0) wids[akey].Bind(wx.EVT_CHECKBOX, Closure(self.onAuto, prop=key)) sizer.Add(wids[akey], (i, 2), (1, 1), LEFT) i += 1 datapush_time = "%.1f" % self.image_panel.datapush_delay wids['dpush_time'] = FloatCtrl(self, value=datapush_time, maxval=1e6, precision=1, minval=0, action=self.onValue, act_on_losefocus=True, action_kw={'prop': 'autosave_time'}, size=(75, -1)) label = 'AutoSave Time (sec)' sizer.Add(self.txt(label), (i, 0), (1, 1), LEFT) sizer.Add(wids['dpush_time'], (i, 1), (1, 1), LEFT) # wids['datapush'].SetValue(1) # wids['datapush'].Bind(wx.EVT_CHECKBOX, self.onEnableDataPush) # sizer.Add(wids['datapush'], (i+1, 0), (1, 3), LEFT) pack(self, sizer) self.__initializing = False self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.onTimer, self.timer) wx.CallAfter(self.onConnect)
class OverlayFrame(wx.Frame): """ settings for overlays and pixel calibration""" shapes = ('None', 'line', 'circle') def __init__(self, image_panel=None, config=None, **kws): wx.Frame.__init__(self, None, -1, style=wx.DEFAULT_FRAME_STYLE, **kws) self.image_panel = image_panel img_x, img_y = self.image_panel.full_size self.wids = wids = [] self.config = config panel = wx.Panel(self) self.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, 0, "")) ok_button = add_button(panel, "Apply", action=self.onApply, size=(75, -1)) done_button = add_button(panel, "Done", action=self.onClose, size=(75, -1)) try: pix_x = float(config['camera']['calib_x']) pix_y = float(config['camera']['calib_y']) except: pix_x = 1.000 pix_y = 1.000 olays = config['overlays'] sbar = [float(x) for x in olays['scalebar'].split()] circ = [float(x) for x in olays['circle'].split()] ssiz, sx, sy, swid, scolr, scolg, scolb = sbar csiz, cx, cy, cwid, ccolr, ccolg, ccolb = circ scol = wx.Colour(int(scolr), int(scolg), int(scolb)) ccol = wx.Colour(int(ccolr), int(ccolg), int(ccolb)) opts = dict(minval=0, maxval=1, precision=3, size=(60, -1)) wopts = dict(minval=0, maxval=10, precision=1, size=(60, -1)) sopts = dict(minval=0, maxval=1000, precision=0, size=(60, -1)) popts = dict(minval=-1000, maxval=1000, precision=3, size=(60, -1)) self.pix_x = FloatCtrl(panel, value=pix_x, **popts) self.pix_y = FloatCtrl(panel, value=pix_y, **popts) self.scalebar_col = csel.ColourSelect(panel, -1, "", scol, size=(75, 25)) self.circle_col = csel.ColourSelect(panel, -1, "", ccol, size=(75, 25)) self.scalebar_size = FloatCtrl(panel, value=ssiz, **sopts) self.scalebar_x = FloatCtrl(panel, value=sx, **opts) self.scalebar_y = FloatCtrl(panel, value=sy, **opts) self.scalebar_wid = FloatCtrl(panel, value=swid, **wopts) self.circle_size = FloatCtrl(panel, value=csiz, **sopts) self.circle_x = FloatCtrl(panel, value=cx, **opts) self.circle_y = FloatCtrl(panel, value=cy, **opts) self.circle_wid = FloatCtrl(panel, value=cwid, **wopts) sizer = wx.GridBagSizer(10, 7) sizer.SetVGap(5) sizer.SetHGap(5) def txt(label, size=-1): return SimpleText(panel, label, size=(size, -1)) sizer.Add(txt(" Configure Image Overlays: "), (0, 0), (1, 4), CEN, 3) sizer.Add(txt(" Pixel Size (um) X, Y: "), (1, 0), (1, 2), LEFT, 2) sizer.Add(self.pix_x, (1, 2), (1, 1), CEN, 1) sizer.Add(self.pix_y, (1, 3), (1, 1), CEN, 1) sizer.Add(txt(" Object "), (2, 0), (1, 1), LEFT, 2) sizer.Add(txt("Color"), (2, 1), (1, 1), LEFT, 2) sizer.Add(txt("Size (um)"), (2, 2), (1, 1), LEFT, 2) sizer.Add(txt("X (fraction)"), (2, 3), (1, 1), LEFT, 2) sizer.Add(txt("Y (fraction)"), (2, 4), (1, 1), LEFT, 2) sizer.Add(txt("Line width"), (2, 5), (1, 1), LEFT, 2) sizer.Add(txt(" Scalebar "), (3, 0), (1, 1), LEFT, 2) sizer.Add(self.scalebar_col, (3, 1), (1, 1), CEN, 1) sizer.Add(self.scalebar_size, (3, 2), (1, 1), CEN, 1) sizer.Add(self.scalebar_x, (3, 3), (1, 1), CEN, 1) sizer.Add(self.scalebar_y, (3, 4), (1, 1), CEN, 1) sizer.Add(self.scalebar_wid, (3, 5), (1, 1), CEN, 1) sizer.Add(txt(" Target "), (4, 0), (1, 1), LEFT, 2) sizer.Add(self.circle_col, (4, 1), (1, 1), CEN, 1) sizer.Add(self.circle_size, (4, 2), (1, 1), CEN, 1) sizer.Add(self.circle_x, (4, 3), (1, 1), CEN, 1) sizer.Add(self.circle_y, (4, 4), (1, 1), CEN, 1) sizer.Add(self.circle_wid, (4, 5), (1, 1), CEN, 1) sizer.Add(wx.StaticLine(panel, size=(220, 2)), (5, 0), (1, 6), wx.ALL | wx.GROW | wx.ALIGN_CENTER, 1) sizer.Add(ok_button, (6, 0), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_CENTER, 1) sizer.Add(done_button, (6, 1), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_CENTER, 1) panel.SetSizer(sizer) sizer.Fit(panel) self.SetSize((500, 225)) self.Bind(wx.EVT_CLOSE, self.onClose) self.Show() self.Raise() def onApply(self, event=None): pix_x = float(self.pix_x.GetValue()) pix_y = float(self.pix_y.GetValue()) self.config['camera']['calib_x'] = "%.4f" % pix_x self.config['camera']['calib_y'] = "%.4f" % pix_y img_x, img_y = self.image_panel.full_size iscale = 0.5 / abs(pix_x * img_x) scol = self.scalebar_col.GetColour() swid = self.scalebar_wid.GetValue() sx = self.scalebar_x.GetValue() sy = self.scalebar_y.GetValue() ssiz = self.scalebar_size.GetValue() ccol = self.circle_col.GetColour() cwid = self.circle_wid.GetValue() csiz = self.circle_size.GetValue() cx = self.circle_x.GetValue() cy = self.circle_y.GetValue() cargs = [cx, cy, csiz * iscale] sargs = [sx - ssiz * iscale, sy, sx + ssiz * iscale, sy] dobjs = [ dict(shape='Line', width=swid, style=wx.SOLID, color=scol, args=sargs), dict(shape='Circle', width=cwid, style=wx.SOLID, color=ccol, args=cargs) ] ofmt = "%.1f %.3f %.3f %.1f %i %i %i" olays = self.config['overlays'] olays['scalebar'] = ofmt % (ssiz, sx, sy, swid, scol[0], scol[1], scol[2]) olays['circle'] = ofmt % (csiz, cx, cy, cwid, ccol[0], ccol[1], ccol[2]) self.image_panel.draw_objects = dobjs def onClose(self, event=None): self.Destroy()
def __init__(self, image_panel=None, config=None, **kws): wx.Frame.__init__(self, None, -1, style=wx.DEFAULT_FRAME_STYLE, **kws) self.image_panel = image_panel img_x, img_y = self.image_panel.full_size self.wids = wids = [] self.config = config panel = wx.Panel(self) self.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, 0, "")) ok_button = add_button(panel, "Apply", action=self.onApply, size=(75, -1)) done_button = add_button(panel, "Done", action=self.onClose, size=(75, -1)) try: pix_x = float(config['camera']['calib_x']) pix_y = float(config['camera']['calib_y']) except: pix_x = 1.000 pix_y = 1.000 olays = config['overlays'] sbar = [float(x) for x in olays['scalebar'].split()] circ = [float(x) for x in olays['circle'].split()] ssiz, sx, sy, swid, scolr, scolg, scolb = sbar csiz, cx, cy, cwid, ccolr, ccolg, ccolb = circ scol = wx.Colour(int(scolr), int(scolg), int(scolb)) ccol = wx.Colour(int(ccolr), int(ccolg), int(ccolb)) opts = dict(minval=0, maxval=1, precision=3, size=(60, -1)) wopts = dict(minval=0, maxval=10, precision=1, size=(60, -1)) sopts = dict(minval=0, maxval=1000, precision=0, size=(60, -1)) popts = dict(minval=-1000, maxval=1000, precision=3, size=(60, -1)) self.pix_x = FloatCtrl(panel, value=pix_x, **popts) self.pix_y = FloatCtrl(panel, value=pix_y, **popts) self.scalebar_col = csel.ColourSelect(panel, -1, "", scol, size=(75, 25)) self.circle_col = csel.ColourSelect(panel, -1, "", ccol, size=(75, 25)) self.scalebar_size = FloatCtrl(panel, value=ssiz, **sopts) self.scalebar_x = FloatCtrl(panel, value=sx, **opts) self.scalebar_y = FloatCtrl(panel, value=sy, **opts) self.scalebar_wid = FloatCtrl(panel, value=swid, **wopts) self.circle_size = FloatCtrl(panel, value=csiz, **sopts) self.circle_x = FloatCtrl(panel, value=cx, **opts) self.circle_y = FloatCtrl(panel, value=cy, **opts) self.circle_wid = FloatCtrl(panel, value=cwid, **wopts) sizer = wx.GridBagSizer(10, 7) sizer.SetVGap(5) sizer.SetHGap(5) def txt(label, size=-1): return SimpleText(panel, label, size=(size, -1)) sizer.Add(txt(" Configure Image Overlays: "), (0, 0), (1, 4), CEN, 3) sizer.Add(txt(" Pixel Size (um) X, Y: "), (1, 0), (1, 2), LEFT, 2) sizer.Add(self.pix_x, (1, 2), (1, 1), CEN, 1) sizer.Add(self.pix_y, (1, 3), (1, 1), CEN, 1) sizer.Add(txt(" Object "), (2, 0), (1, 1), LEFT, 2) sizer.Add(txt("Color"), (2, 1), (1, 1), LEFT, 2) sizer.Add(txt("Size (um)"), (2, 2), (1, 1), LEFT, 2) sizer.Add(txt("X (fraction)"), (2, 3), (1, 1), LEFT, 2) sizer.Add(txt("Y (fraction)"), (2, 4), (1, 1), LEFT, 2) sizer.Add(txt("Line width"), (2, 5), (1, 1), LEFT, 2) sizer.Add(txt(" Scalebar "), (3, 0), (1, 1), LEFT, 2) sizer.Add(self.scalebar_col, (3, 1), (1, 1), CEN, 1) sizer.Add(self.scalebar_size, (3, 2), (1, 1), CEN, 1) sizer.Add(self.scalebar_x, (3, 3), (1, 1), CEN, 1) sizer.Add(self.scalebar_y, (3, 4), (1, 1), CEN, 1) sizer.Add(self.scalebar_wid, (3, 5), (1, 1), CEN, 1) sizer.Add(txt(" Target "), (4, 0), (1, 1), LEFT, 2) sizer.Add(self.circle_col, (4, 1), (1, 1), CEN, 1) sizer.Add(self.circle_size, (4, 2), (1, 1), CEN, 1) sizer.Add(self.circle_x, (4, 3), (1, 1), CEN, 1) sizer.Add(self.circle_y, (4, 4), (1, 1), CEN, 1) sizer.Add(self.circle_wid, (4, 5), (1, 1), CEN, 1) sizer.Add(wx.StaticLine(panel, size=(220, 2)), (5, 0), (1, 6), wx.ALL | wx.GROW | wx.ALIGN_CENTER, 1) sizer.Add(ok_button, (6, 0), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_CENTER, 1) sizer.Add(done_button, (6, 1), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_CENTER, 1) panel.SetSizer(sizer) sizer.Fit(panel) self.SetSize((500, 225)) self.Bind(wx.EVT_CLOSE, self.onClose) self.Show() self.Raise()
def __init__(self, parent, image_panel=None, camera_id=0, center_cb=None, xhair_cb=None, **kws): super(ConfPanel_PySpin, self).__init__(parent, center_cb=center_cb, xhair_cb=xhair_cb, **kws) self.image_panel = image_panel self.camera_id = camera_id self.camera = self.image_panel.camera wids = self.wids sizer = self.sizer with_color_conv = False self.title = self.txt("PySpinnaker: ", size=285) self.title2 = self.txt(" ", size=285) self.title3 = self.txt(" ", size=285) btn_start = add_button(self, "Restart Camera", action=self.onRestart, size=(250, -1)) next_row = self.show_position_info(row=0) sizer.Add(self.title, (next_row, 0), (1, 3), LEFT) sizer.Add(self.title2, (next_row + 1, 0), (1, 3), LEFT) sizer.Add(self.title3, (next_row + 2, 0), (1, 3), LEFT) self.__initializing = True i = next_row + 3 for dat in (('exposure', 'ms', 50, 0.03, MAX_EXPOSURE_TIME), ('gain', 'dB', 5, 0, 40)): # ('gamma', '', 1, 0.5, 4)): key, units, defval, minval, maxval = dat wids[key] = FloatCtrl(self, value=defval, minval=minval, maxval=maxval, precision=2, action=self.onValue, act_on_losefocus=True, action_kw={'prop': key}, size=(75, -1)) label = '%s' % (key.title()) if len(units) > 0: label = '%s (%s)' % (key.title(), units) sizer.Add(self.txt(label), (i, 0), (1, 1), LEFT) sizer.Add(wids[key], (i, 1), (1, 1), LEFT) if key != 'gamma': akey = '%s_auto' % key wids[akey] = wx.CheckBox(self, -1, label='auto') wids[akey].SetValue(0) wids[akey].Bind(wx.EVT_CHECKBOX, Closure(self.onAuto, prop=key)) sizer.Add(wids[akey], (i, 2), (1, 1), LEFT) i = i + 1 for color in ('blue', 'red'): key = 'wb_%s' % color wids[key] = FloatCtrl(self, value=0, minval=0.3, maxval=4, precision=3, action=self.onValue, act_on_losefocus=True, action_kw={'prop': key}, size=(75, -1)) wids[key].Disable() label = 'White Balance (%s)' % (color) sizer.Add(self.txt(label), (i, 0), (1, 1), LEFT) sizer.Add(wids[key], (i, 1), (1, 1), LEFT) if color == 'blue': akey = 'wb_auto' wids[akey] = wx.CheckBox(self, -1, label='auto') wids[akey].SetValue(0) wids[akey].Bind(wx.EVT_CHECKBOX, Closure(self.onAuto, prop=key)) sizer.Add(wids[akey], (i, 2), (1, 1), LEFT) i += 1 datapush_time = "%.1f" % self.image_panel.datapush_delay wids['dpush_time'] = FloatCtrl(self, value=datapush_time, maxval=1e6, precision=1, minval=0, action=self.onValue, act_on_losefocus=True, action_kw={'prop': 'autosave_time'}, size=(75, -1)) label = 'AutoSave Time (sec)' sizer.Add(self.txt(label), (i, 0), (1, 1), LEFT) sizer.Add(wids['dpush_time'], (i, 1), (1, 1), LEFT) i = i + 1 sizer.Add(btn_start, (i, 0), (1, 2), LEFT) if with_color_conv: conv_choices = ('DEFAULT', 'NO_COLOR_PROCESSING', 'NEAREST_NEIGHBOR', 'EDGE_SENSING', 'HQ_LINEAR', 'RIGOROUS', 'IPP', 'DIRECTIONAL_FILTER', 'WEIGHTED_DIRECTIONAL_FILTER') wids['color_conv'] = wx.Choice(self, -1, choices=conv_choices, size=(150, -1)) wids['color_conv'].Bind(wx.EVT_CHOICE, self.onColorConv) i += 1 sizer.Add(self.txt('Conversion: '), (i, 0), (1, 1), LEFT) sizer.Add(wids['color_conv'], (i, 1), (1, 1), LEFT) # wids['datapush'].SetValue(1) # wids['datapush'].Bind(wx.EVT_CHECKBOX, self.onEnableDataPush) # sizer.Add(wids['datapush'], (i+1, 0), (1, 3), LEFT) pack(self, sizer) self.__initializing = False self.read_props_timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.onTimer, self.read_props_timer) wx.CallAfter(self.onConnect)
def build_dialog(self): positions = self.instdb.get_positionlist(self.offline) panel = scrolled.ScrolledPanel(self) self.checkboxes = OrderedDict() sizer = wx.GridBagSizer(len(positions) + 5, 4) sizer.SetVGap(2) sizer.SetHGap(3) bkws = dict(size=(95, -1)) btn_ok = add_button(panel, "Copy Selected", action=self.onOK, **bkws) btn_all = add_button(panel, "Select All", action=self.onAll, **bkws) btn_none = add_button(panel, "Select None", action=self.onNone, **bkws) brow = wx.BoxSizer(wx.HORIZONTAL) brow.Add(btn_all, 0, ALL_EXP | wx.ALIGN_LEFT, 1) brow.Add(btn_none, 0, ALL_EXP | wx.ALIGN_LEFT, 1) brow.Add(btn_ok, 0, ALL_EXP | wx.ALIGN_LEFT, 1) self.suffix = wx.TextCtrl(panel, value="", size=(150, -1)) self.xoff = FloatCtrl(panel, value=0, precision=3, size=(75, -1)) self.yoff = FloatCtrl(panel, value=0, precision=3, size=(75, -1)) self.zoff = FloatCtrl(panel, value=0, precision=3, size=(75, -1)) irow = 0 sizer.Add(brow, (irow, 0), (1, 4), LEFT_CEN, 2) irow += 1 sizer.Add(SimpleText(panel, ' Add Suffix:'), (irow, 0), (1, 1), LEFT_CEN, 2) sizer.Add(self.suffix, (irow, 1), (1, 3), LEFT_CEN, 2) irow += 1 sizer.Add(SimpleText(panel, 'Offsets X, Y, Z:'), (irow, 0), (1, 1), LEFT_CEN, 2) sizer.Add(self.xoff, (irow, 1), (1, 1), LEFT_CEN, 2) sizer.Add(self.yoff, (irow, 2), (1, 1), LEFT_CEN, 2) sizer.Add(self.zoff, (irow, 3), (1, 1), LEFT_CEN, 2) irow += 1 sizer.Add(SimpleText(panel, ' Position Name'), (irow, 0), (1, 1), LEFT_CEN, 2) sizer.Add(SimpleText(panel, 'Copy?'), (irow, 1), (1, 1), LEFT_CEN, 2) sizer.Add(SimpleText(panel, ' Position Name'), (irow, 2), (1, 1), LEFT_CEN, 2) sizer.Add(SimpleText(panel, 'Copy?'), (irow, 3), (1, 1), LEFT_CEN, 2) irow += 1 sizer.Add(wx.StaticLine(panel, size=(500, 2)), (irow, 0), (1, 4), LEFT_CEN, 2) for ip, pname in enumerate(positions): cbox = self.checkboxes[pname] = wx.CheckBox(panel, -1, "") cbox.SetValue(True) if ip % 2 == 0: irow += 1 icol = 0 else: icol = 2 sizer.Add(SimpleText(panel, " %s " % pname), (irow, icol), (1, 1), LEFT_CEN, 2) sizer.Add(cbox, (irow, icol + 1), (1, 1), LEFT_CEN, 2) irow += 1 sizer.Add(wx.StaticLine(panel, size=(500, 2)), (irow, 0), (1, 4), LEFT_CEN, 2) pack(panel, sizer) panel.SetMinSize((700, 550)) panel.SetupScrolling() mainsizer = wx.BoxSizer(wx.VERTICAL) mainsizer.Add(panel, 1, ALL_EXP | wx.GROW | wx.ALIGN_LEFT, 1) pack(self, mainsizer) self.SetMinSize((700, 550)) self.Raise() self.Show()
class TransferPositionsDialog(wx.Frame): """ transfer positions from offline microscope""" def __init__(self, offline, instname=None, instdb=None, parent=None): wx.Frame.__init__(self, None, -1, title="Copy Positions from Offline Microscope") self.offline = offline self.instname = instname self.parent = parent self.instdb = instdb self.build_dialog() def build_dialog(self): positions = self.instdb.get_positionlist(self.offline) panel = scrolled.ScrolledPanel(self) self.checkboxes = OrderedDict() sizer = wx.GridBagSizer(len(positions) + 5, 4) sizer.SetVGap(2) sizer.SetHGap(3) bkws = dict(size=(95, -1)) btn_ok = add_button(panel, "Copy Selected", action=self.onOK, **bkws) btn_all = add_button(panel, "Select All", action=self.onAll, **bkws) btn_none = add_button(panel, "Select None", action=self.onNone, **bkws) brow = wx.BoxSizer(wx.HORIZONTAL) brow.Add(btn_all, 0, ALL_EXP | wx.ALIGN_LEFT, 1) brow.Add(btn_none, 0, ALL_EXP | wx.ALIGN_LEFT, 1) brow.Add(btn_ok, 0, ALL_EXP | wx.ALIGN_LEFT, 1) self.suffix = wx.TextCtrl(panel, value="", size=(150, -1)) self.xoff = FloatCtrl(panel, value=0, precision=3, size=(75, -1)) self.yoff = FloatCtrl(panel, value=0, precision=3, size=(75, -1)) self.zoff = FloatCtrl(panel, value=0, precision=3, size=(75, -1)) irow = 0 sizer.Add(brow, (irow, 0), (1, 4), LEFT_CEN, 2) irow += 1 sizer.Add(SimpleText(panel, ' Add Suffix:'), (irow, 0), (1, 1), LEFT_CEN, 2) sizer.Add(self.suffix, (irow, 1), (1, 3), LEFT_CEN, 2) irow += 1 sizer.Add(SimpleText(panel, 'Offsets X, Y, Z:'), (irow, 0), (1, 1), LEFT_CEN, 2) sizer.Add(self.xoff, (irow, 1), (1, 1), LEFT_CEN, 2) sizer.Add(self.yoff, (irow, 2), (1, 1), LEFT_CEN, 2) sizer.Add(self.zoff, (irow, 3), (1, 1), LEFT_CEN, 2) irow += 1 sizer.Add(SimpleText(panel, ' Position Name'), (irow, 0), (1, 1), LEFT_CEN, 2) sizer.Add(SimpleText(panel, 'Copy?'), (irow, 1), (1, 1), LEFT_CEN, 2) sizer.Add(SimpleText(panel, ' Position Name'), (irow, 2), (1, 1), LEFT_CEN, 2) sizer.Add(SimpleText(panel, 'Copy?'), (irow, 3), (1, 1), LEFT_CEN, 2) irow += 1 sizer.Add(wx.StaticLine(panel, size=(500, 2)), (irow, 0), (1, 4), LEFT_CEN, 2) for ip, pname in enumerate(positions): cbox = self.checkboxes[pname] = wx.CheckBox(panel, -1, "") cbox.SetValue(True) if ip % 2 == 0: irow += 1 icol = 0 else: icol = 2 sizer.Add(SimpleText(panel, " %s " % pname), (irow, icol), (1, 1), LEFT_CEN, 2) sizer.Add(cbox, (irow, icol + 1), (1, 1), LEFT_CEN, 2) irow += 1 sizer.Add(wx.StaticLine(panel, size=(500, 2)), (irow, 0), (1, 4), LEFT_CEN, 2) pack(panel, sizer) panel.SetMinSize((700, 550)) panel.SetupScrolling() mainsizer = wx.BoxSizer(wx.VERTICAL) mainsizer.Add(panel, 1, ALL_EXP | wx.GROW | wx.ALIGN_LEFT, 1) pack(self, mainsizer) self.SetMinSize((700, 550)) self.Raise() self.Show() def onAll(self, event=None): for cbox in self.checkboxes.values(): cbox.SetValue(True) def onNone(self, event=None): for cbox in self.checkboxes.values(): cbox.SetValue(False) def onOK(self, event=None): if self.instname is not None and self.instdb is not None: suff = self.suffix.GetValue() idb = self.instdb uscope = idb.get_instrument(self.offline) sample = idb.get_instrument(self.instname) uname = uscope.name.replace(' ', '_') sname = sample.name.replace(' ', '_') conf_name = "CoordTrans:%s:%s" % (uname, sname) conf = json.loads(idb.scandb.get_config(conf_name).notes) source_pvs = conf['source'] dest_pvs = conf['dest'] rotmat = np.array(conf['rotmat']) upos = OrderedDict() for pname, cbox in self.checkboxes.items(): if cbox.IsChecked(): v = idb.get_position_vals(self.offline, pname) upos[pname] = [v[pvn] for pvn in source_pvs] newnames = upos.keys() vals = np.ones((4, len(upos))) for i, pname in enumerate(newnames): vals[0, i] = upos[pname][0] vals[1, i] = upos[pname][1] vals[2, i] = upos[pname][2] pred = np.dot(rotmat, vals) poslist = idb.get_positionlist(self.instname) saved_temp = None if len(poslist) < 1 and self.parent is not None: saved_temp = '__tmp__' if saved_temp in newnames: saved_temp = '__tmp_a0012AZqspkwx9827nf917+o,ppa+' self.parent.onSave(saved_temp) time.sleep(3.0) poslist = idb.get_positionlist(self.instname) pos0 = idb.get_position_vals(self.instname, poslist[0]) pvs = pos0.keys() pvs.sort() spos = OrderedDict() for pvname in pvs: spos[pvname] = 0.000 xoffset = self.xoff.GetValue() yoffset = self.yoff.GetValue() zoffset = self.zoff.GetValue() xpv, ypv, zpv = dest_pvs for i, pname in enumerate(newnames): spos[xpv] = pred[0, i] + xoffset spos[ypv] = pred[1, i] + yoffset spos[zpv] = pred[2, i] + zoffset nlabel = '%s%s' % (pname, suff) idb.save_position(self.instname, nlabel, spos) if saved_temp is not None: self.parent.onErase(posname=saved_temp, query=False) self.Destroy() def onCancel(self, event=None): self.Destroy()