def onShowIntegration(self, event=None): if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern()
def ShowPlotFrame(self, do_raise=True, clear=True): "make sure plot frame is enabled, and visible" if self.plotframe is None: self.plotframe = PlotFrame(self) self.has_plot = False try: self.plotframe.Show() except wx.PyDeadObjectError: self.plotframe = PlotFrame(self) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config()
def ShowPlotFrame(self, do_raise=True, clear=True): "make sure plot frame is enabled, and visible" if self.plotframe is None: self.plotframe = PlotFrame(self) self.has_plot = False try: self.plotframe.Show() except PyDeadObjectError: self.plotframe = PlotFrame(self) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config()
class TestFrame(wx.Frame): def __init__(self, parent=None, *args, **kwds): kwds[ "style"] = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.TAB_TRAVERSAL wx.Frame.__init__(self, parent, wx.NewId(), '', wx.DefaultPosition, wx.Size(-1, -1), **kwds) self.SetTitle(" WXMPlot Plotting Demo") self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False)) self.plotframe = None self.Bind(wx.EVT_TIMER, self.onTimer) self.timer = wx.Timer(self) self.Refresh() self.ShowPlotFrame(do_raise=False, clear=False) self.onStartTimer() def ShowPlotFrame(self, do_raise=True, clear=True): "make sure plot frame is enabled, and visible" if self.plotframe is None: self.plotframe = PlotFrame(self) self.has_plot = False try: self.plotframe.Show() except PyDeadObjectError: self.plotframe = PlotFrame(self) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config() def onStartTimer(self, event=None): self.count = 0 self.timer.Start(1) def onTimer(self, event): # print 'timer ', self.count, time.time() self.count += 1 self.x = arange(0.0, 3, 0.01) self.y = sin(2 * pi * self.x + self.count) self.plotframe.plot(self.x, self.y) def OnExit(self, event): try: if self.plotframe != None: self.plotframe.onExit() except: pass self.Destroy()
def onAutoIntegration(self, event=None): if not event.IsChecked(): self.int_timer.Stop() return if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() self.int_timer.Start(500)
def ShowPlotFrame(self, do_raise=True, clear=True): """make sure plot frame is enabled, and visible""" if self.plotframe is None: self.plotframe = PlotFrame(self, axissize=[0.08, 0.06, 0.91, 0.92]) # self.has_plot = False try: self.plotframe.Show() except wx.PyDeadObjectError: self.plotframe = PlotFrame(self, axissize=[0.08, 0.06, 0.91, 0.92]) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config() self.plotYdata = [] self.plotXdata = []
class TestFrame(wx.Frame): def __init__(self, parent=None, *args,**kwds): kwds["style"] = wx.DEFAULT_FRAME_STYLE|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL wx.Frame.__init__(self, parent, wx.NewId(), '', wx.DefaultPosition, wx.Size(-1,-1), **kwds) self.SetTitle("signal test") self.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.BOLD,False)) self.plotframe = None self.Bind(wx.EVT_TIMER, self.onTimer) self.timer = wx.Timer(self) #slider self.sld = wx.Slider(self, value = 973, minValue = 800, maxValue = 1100, style = wx.SL_HORIZONTAL) self.sld.Bind(wx.EVT_SLIDER, self.OnSliderScroll) self.Refresh() self.ShowPlotFrame(do_raise=False, clear=False) self.onStartTimer() def ShowPlotFrame(self, do_raise=True, clear=True): "make sure plot frame is enabled, and visible" if self.plotframe is None: self.plotframe = PlotFrame(self) self.has_plot = False try: self.plotframe.Show() except PyDeadObjectError: self.plotframe = PlotFrame(self) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config() def onStartTimer(self,event=None): self.count = 0 self.timer.Start(1) def onTimer(self, event): # print 'timer ', self.count, time.time() self.count += 1 N_Samples = 256 * 1024 samples = sdr.read_samples(N_Samples) interval = 2048 N = N_Samples//interval * interval y = samples[:N] y = y[:len(y//interval*interval)] y = y.reshape(N//interval, interval) y_windowed = y*np.kaiser(interval, 6) Y = fftshift(fft(y_windowed,axis=1),axes=1) Pspect = np.mean(abs(Y)*abs(Y),axis=0); self.plotframe.plot(np.arange(0, len(Pspect), 1),Pspect) def OnExit(self, event): try: if self.plotframe != None: self.plotframe.onExit() except: pass self.Destroy() def OnSliderScroll(self, e): obj = e.GetEventObject() val = obj.GetValue() sdr.center_freq = val * 1e5 print("frequency: "+str(sdr.center_freq / 10e6)+"MHz")
def onProfile(self, x0, y0, x1, y1): width = self.ad_cam.SizeX height = self.ad_cam.SizeY x0, y0 = int(x0 * width), int(y0 * height) x1, y1 = int(x1 * width), int(y1 * height) dx, dy = abs(x1 - x0), abs(y1 - y0) if dx < 2 and dy < 2: return outdat = [] if self.colormode == 2: self.data.shape = (self.im_size[1], self.im_size[0], 3) else: self.data.shape = self.im_size[1], self.im_size[0] if dy > dx: _y0 = min(int(y0), int(y1 + 0.5)) _y1 = max(int(y0), int(y1 + 0.5)) for iy in range(_y0, _y1): ix = int(x0 + (iy - int(y0)) * (x1 - x0) / (y1 - y0)) outdat.append((ix, iy)) else: _x0 = min(int(x0), int(x1 + 0.5)) _x1 = max(int(x0), int(x1 + 0.5)) for ix in range(_x0, _x1): iy = int(y0 + (ix - int(x0)) * (y1 - y0) / (x1 - x0)) outdat.append((ix, iy)) if self.lineplotter is None: self.lineplotter = PlotFrame(self, title='Image Profile') else: try: self.lineplotter.Raise() except PyDeadObjectError: self.lineplotter = PlotFrame(self, title='Image Profile') if self.colormode == 2: x, y, r, g, b = [], [], [], [], [] for ix, iy in outdat: x.append(ix) y.append(iy) r.append(self.data[iy, ix, 0]) g.append(self.data[iy, ix, 1]) b.append(self.data[iy, ix, 2]) xlabel = 'Pixel (x)' if dy > dx: x = y xlabel = 'Pixel (y)' self.lineplotter.plot(x, r, color='red', label='red', xlabel=xlabel, ylabel='Intensity', title='Image %i' % self.ad_cam.ArrayCounter_RBV) self.lineplotter.oplot(x, g, color='green', label='green') self.lineplotter.oplot(x, b, color='blue', label='blue') else: x, y, z = [], [], [] for ix, iy in outdat: x.append(ix) y.append(iy) z.append(self.data[iy, ix]) xlabel = 'Pixel (x)' if dy > dx: x = y xlabel = 'Pixel (y)' self.lineplotter.plot(x, z, color='k', xlabel=xlabel, ylabel='Intensity', title='Image %i' % self.ad_cam.ArrayCounter_RBV) self.lineplotter.Show() self.lineplotter.Raise()
class AD_Display(wx.Frame): """AreaDetector Display """ img_attrs = ('ArrayData', 'UniqueId_RBV', 'NDimensions_RBV', 'ArraySize0_RBV', 'ArraySize1_RBV', 'ArraySize2_RBV', 'ColorMode_RBV') cam_attrs = ('Acquire', 'ArrayCounter', 'ArrayCounter_RBV', 'DetectorState_RBV', 'NumImages', 'ColorMode', 'DataType_RBV', 'Gain', 'AcquireTime', 'AcquirePeriod', 'ImageMode', 'MaxSizeX_RBV', 'MaxSizeY_RBV', 'TriggerMode', 'SizeX', 'SizeY', 'MinX', 'MinY') # plugins to enable enabled_plugins = ('image1', 'Over1', 'ROI1', 'JPEG1', 'TIFF1') stat_msg = 'Read %.1f%% of images: rate=%.1f frames/sec' def __init__(self, prefix=None, app=None, scale=1.0, approx_height=1200, known_cameras=None): self.app = app self.ad_img = None self.ad_cam = None self.imgcount = 0 self.prefix = prefix self.fname = 'AD_Image.tiff' self.scale = scale self.known_cameras = known_cameras self.arrsize = [0, 0, 0] self.imbuff = None self.d_size = None self.im_size = None self.colormode = 0 self.last_update = 0.0 self.n_img = 0 self.imgcount_start = 0 self.n_drawn = 0 self.img_id = 0 self.starttime = time.time() self.drawing = False self.lineplotter = None self.zoom_lims = [] wx.Frame.__init__(self, None, -1, "Epics Area Detector Display", style=wx.DEFAULT_FRAME_STYLE) if known_cameras is not None: self.ConnectToCamera(name=self.prefix) else: self.ConnectToPV(name=self.prefix) self.img_w = 0 self.img_h = 0 self.wximage = wx.EmptyImage( 1024, 1360) # 1360, 1024) # approx_height, 1.5*approx_height) self.buildMenus() self.buildFrame() def OnLeftUp(self, event): if self.image is not None: self.image.OnLeftUp(event) def ConnectToCamera(self, name=None, event=None): if name is None: name = '' if self.known_cameras is None: return cam_names = self.known_cameras.keys() cam_names.sort() dlg = wx.SingleChoiceDialog(self, 'Select Camera', caption='Select Camera', choices=cam_names) dlg.Raise() if dlg.ShowModal() == wx.ID_OK: cname = dlg.GetStringSelection() if cname in self.known_cameras: self.prefix = self.known_cameras[cname] wx.CallAfter(self.connect_pvs) dlg.Destroy() def ConnectToPV(self, event=None, name=None): print 'Connect To PV ', name, event if name is None: name = '' dlg = wx.TextEntryDialog(self, 'Enter PV for Area Detector', caption='Enter PV for Area Detector', defaultValue=name) dlg.Raise() if dlg.ShowModal() == wx.ID_OK: self.prefix = dlg.GetValue() wx.CallAfter(self.connect_pvs) dlg.Destroy() def onCopyImage(self, event=None): "copy bitmap of canvas to system clipboard" bmp = wx.BitmapDataObject() bmp.SetBitmap(wx.BitmapFromImage(self.wximage)) wx.TheClipboard.Open() wx.TheClipboard.SetData(bmp) wx.TheClipboard.Close() wx.TheClipboard.Flush() @EpicsFunction def CameraOff(self): try: self.ad_cam.Acquire = 0 except: pass @EpicsFunction def onSaveImage(self, event=None): "prompts for and save image to file" defdir = os.getcwd() self.fname = "Image_%i.tiff" % self.ad_cam.ArrayCounter_RBV dlg = wx.FileDialog(None, message='Save Image as', defaultDir=os.getcwd(), defaultFile=self.fname, style=wx.SAVE) path = None if dlg.ShowModal() == wx.ID_OK: path = os.path.abspath(dlg.GetPath()) dlg.Destroy() if path is not None and self.data is not None: Image.frombuffer(self.im_mode, self.im_size, self.data.flatten(), 'raw', self.im_mode, 0, 1).save(path) def onExit(self, event=None): try: wx.Yield() except: pass self.CameraOff() self.Destroy() def onAbout(self, event=None): msg = """Epics Image Display version 0.2 http://pyepics.github.com/epicsapps/ Matt Newville <*****@*****.**>""" dlg = wx.MessageDialog(self, msg, "About Epics Image Display", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def buildMenus(self): fmenu = wx.Menu() add_menu(self, fmenu, "&Connect to Pre-defiend Camera", "Connect to PV", self.ConnectToCamera) add_menu(self, fmenu, "&Connect to AreaDetector PV\tCtrl+O", "Connect to PV", self.ConnectToPV) add_menu(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage) add_menu(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard", self.onCopyImage) fmenu.AppendSeparator() add_menu(self, fmenu, "E&xit\tCtrl+Q", "Exit Program", self.onExit) omenu = wx.Menu() add_menu(self, omenu, "&Zoom out\tCtrl+Z", "Zoom Out", self.unZoom) add_menu(self, omenu, "Reset Image Counter", "Set Image Counter to 0", self.onResetImageCounter) omenu.AppendSeparator() add_menu(self, omenu, "&Rotate Clockwise\tCtrl+R", "Rotate Clockwise", self.onRotCW) add_menu(self, omenu, "Rotate CounterClockwise", "Rotate Counter Clockwise", self.onRotCCW) add_menu(self, omenu, "Flip Up/Down\tCtrl+T", "Flip Up/Down", self.onFlipV) add_menu(self, omenu, "Flip Left/Right\tCtrl+F", "Flip Left/Right", self.onFlipH) omenu.AppendSeparator() self.CM_ZOOM = wx.NewId() self.CM_SHOW = wx.NewId() self.CM_PROF = wx.NewId() omenu.Append(self.CM_ZOOM, "Cursor Mode: Zoom to Box\tCtrl+B", "Zoom to box by clicking and dragging", wx.ITEM_RADIO) omenu.Append(self.CM_SHOW, "Cursor Mode: Show X,Y\tCtrl+X", "Show X,Y, Intensity Values", wx.ITEM_RADIO) omenu.Append(self.CM_PROF, "Cursor Mode: Line Profile\tCtrl+L", "Show Line Profile", wx.ITEM_RADIO) self.Bind(wx.EVT_MENU, self.onCursorMode, id=self.CM_ZOOM) self.Bind(wx.EVT_MENU, self.onCursorMode, id=self.CM_PROF) self.Bind(wx.EVT_MENU, self.onCursorMode, id=self.CM_SHOW) hmenu = wx.Menu() add_menu(self, hmenu, "About", "About Epics AreadDetector Display", self.onAbout) mbar = wx.MenuBar() mbar.Append(fmenu, "File") mbar.Append(omenu, "Options") mbar.Append(hmenu, "&Help") self.SetMenuBar(mbar) def onCursorMode(self, event=None): if event.Id == self.CM_ZOOM: self.image.cursor_mode = 'zoom' elif event.Id == self.CM_PROF: self.image.cursor_mode = 'profile' elif event.Id == self.CM_SHOW: self.image.cursor_mode = 'show' @DelayedEpicsCallback def onResetImageCounter(self, event=None): self.ad_cam.ArrayCounter = 0 def onRotCW(self, event): self.image.rot90 = (self.image.rot90 + 1) % 4 self.image.Refresh() def onRotCCW(self, event): self.image.rot90 = (self.image.rot90 - 1) % 4 self.image.Refresh() def onFlipV(self, event): self.image.flipv = not self.image.flipv self.image.Refresh() def onFlipH(self, event): self.image.fliph = not self.image.fliph self.image.Refresh() def buildFrame(self): sbar = self.CreateStatusBar(3, wx.CAPTION | wx.THICK_FRAME) sfont = sbar.GetFont() sfont.SetWeight(wx.BOLD) sfont.SetPointSize(10) sbar.SetFont(sfont) self.SetStatusWidths([-3, -1, -1]) self.SetStatusText('', 0) sizer = wx.GridBagSizer(10, 4) panel = wx.Panel(self) self.panel = panel labstyle = wx.ALIGN_LEFT | wx.ALIGN_BOTTOM | wx.EXPAND ctrlstyle = wx.ALIGN_LEFT | wx.ALIGN_BOTTOM rlabstyle = wx.ALIGN_RIGHT | wx.RIGHT | wx.TOP | wx.EXPAND txtstyle = wx.ALIGN_LEFT | wx.ST_NO_AUTORESIZE | wx.TE_PROCESS_ENTER self.wids = {} self.wids['exptime'] = PVFloatCtrl(panel, pv=None, size=(100, -1)) self.wids['period'] = PVFloatCtrl(panel, pv=None, size=(100, -1)) self.wids['numimages'] = PVFloatCtrl(panel, pv=None, size=(100, -1)) self.wids['gain'] = PVFloatCtrl(panel, pv=None, size=(100, -1), minval=0, maxval=20) self.wids['imagemode'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['triggermode'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['color'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['start'] = wx.Button(panel, -1, label='Start', size=(50, -1)) self.wids['stop'] = wx.Button(panel, -1, label='Stop', size=(50, -1)) if HAS_OVERLAY_DEVICE: self.wids['o1color'] = csel.ColourSelect(panel, -1, "", '#FEFEFE', size=(60, 25)) self.wids['o1color'].Bind(csel.EVT_COLOURSELECT, Closure(self.onColor, item=1)) self.wids['o1posx'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o1posy'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o1sizx'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o1sizy'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o1shape'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['o1use'] = PVEnumChoice(panel, pv=None, size=(50, -1)) self.wids['o1name'] = PVTextCtrl(panel, pv=None, size=(100, -1)) self.wids['o2color'] = csel.ColourSelect(panel, -1, "", '#FEFEFE', size=(60, 25)) self.wids['o2color'].Bind(csel.EVT_COLOURSELECT, Closure(self.onColor, item=2)) self.wids['o2posx'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o2posy'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o2sizx'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o2sizy'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o2shape'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['o2use'] = PVEnumChoice(panel, pv=None, size=(50, -1)) self.wids['o2name'] = PVTextCtrl(panel, pv=None, size=(100, -1)) for key in ('start', 'stop'): self.wids[key].Bind(wx.EVT_BUTTON, Closure(self.onEntry, key=key)) self.wids['zoomsize'] = wx.StaticText(panel, -1, size=(250, -1), style=txtstyle) self.wids['fullsize'] = wx.StaticText(panel, -1, size=(250, -1), style=txtstyle) def txt(label, size=100): return wx.StaticText(panel, label=label, size=(size, -1), style=labstyle) def lin(len=30, wid=2, style=wx.LI_HORIZONTAL): return wx.StaticLine(panel, size=(len, wid), style=style) sizer.Add(txt(' '), (0, 0), (1, 1), labstyle) sizer.Add(txt('Image Mode '), (1, 0), (1, 1), labstyle) sizer.Add(self.wids['imagemode'], (1, 1), (1, 2), ctrlstyle) sizer.Add(txt('# Images '), (2, 0), (1, 1), labstyle) sizer.Add(self.wids['numimages'], (2, 1), (1, 2), ctrlstyle) sizer.Add(txt('Trigger Mode '), (3, 0), (1, 1), labstyle) sizer.Add(self.wids['triggermode'], (3, 1), (1, 2), ctrlstyle) sizer.Add(txt('Period '), (4, 0), (1, 1), labstyle) sizer.Add(self.wids['period'], (4, 1), (1, 2), ctrlstyle) sizer.Add(txt('Exposure Time '), (5, 0), (1, 1), labstyle) sizer.Add(self.wids['exptime'], (5, 1), (1, 2), ctrlstyle) sizer.Add(txt('Gain '), (6, 0), (1, 1), labstyle) sizer.Add(self.wids['gain'], (6, 1), (1, 2), ctrlstyle) sizer.Add(txt('Color Mode'), (7, 0), (1, 1), labstyle) sizer.Add(self.wids['color'], (7, 1), (1, 2), ctrlstyle) sizer.Add(txt('Acquire '), (9, 0), (1, 1), labstyle) sizer.Add(self.wids['start'], (9, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['stop'], (9, 2), (1, 1), ctrlstyle) sizer.Add(self.wids['fullsize'], (12, 0), (1, 3), labstyle) sizer.Add(self.wids['zoomsize'], (13, 0), (1, 3), labstyle) sizer.Add(lin(75), (15, 0), (1, 3), labstyle) if HAS_OVERLAY_DEVICE: ir = 16 sizer.Add(txt('Overlay 1:'), (ir + 0, 0), (1, 1), labstyle) sizer.Add(self.wids['o1use'], (ir + 0, 1), (1, 2), ctrlstyle) sizer.Add(txt('Shape:'), (ir + 1, 0), (1, 1), labstyle) sizer.Add(self.wids['o1shape'], (ir + 1, 1), (1, 2), ctrlstyle) sizer.Add(txt('Name:'), (ir + 2, 0), (1, 1), labstyle) sizer.Add(self.wids['o1name'], (ir + 2, 1), (1, 2), ctrlstyle) sizer.Add(txt('Position '), (ir + 3, 0), (1, 1), labstyle) sizer.Add(self.wids['o1posx'], (ir + 3, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['o1posy'], (ir + 3, 2), (1, 1), ctrlstyle) sizer.Add(txt('Size '), (ir + 4, 0), (1, 1), labstyle) sizer.Add(self.wids['o1sizx'], (ir + 4, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['o1sizy'], (ir + 4, 2), (1, 1), ctrlstyle) sizer.Add(txt('Color '), (ir + 5, 0), (1, 1), labstyle) sizer.Add(self.wids['o1color'], (ir + 5, 1), (1, 2), ctrlstyle) sizer.Add(lin(75), (ir + 6, 0), (1, 3), labstyle) ir = ir + 7 sizer.Add(txt('Overlay 1:'), (ir + 0, 0), (1, 1), labstyle) sizer.Add(self.wids['o2use'], (ir + 0, 1), (1, 2), ctrlstyle) sizer.Add(txt('Shape:'), (ir + 1, 0), (1, 1), labstyle) sizer.Add(self.wids['o2shape'], (ir + 1, 1), (1, 2), ctrlstyle) sizer.Add(txt('Name:'), (ir + 2, 0), (1, 1), labstyle) sizer.Add(self.wids['o2name'], (ir + 2, 1), (1, 2), ctrlstyle) sizer.Add(txt('Position '), (ir + 3, 0), (1, 1), labstyle) sizer.Add(self.wids['o2posx'], (ir + 3, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['o2posy'], (ir + 3, 2), (1, 1), ctrlstyle) sizer.Add(txt('Size '), (ir + 4, 0), (1, 1), labstyle) sizer.Add(self.wids['o2sizx'], (ir + 4, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['o2sizy'], (ir + 4, 2), (1, 1), ctrlstyle) sizer.Add(txt('Color '), (ir + 5, 0), (1, 1), labstyle) sizer.Add(self.wids['o2color'], (ir + 5, 1), (1, 2), ctrlstyle) sizer.Add(lin(75), (ir + 6, 0), (1, 3), labstyle) self.image = ImageView(self, size=(1360, 1024), onzoom=self.onZoom, onprofile=self.onProfile, onshow=self.onShowXY) panel.SetSizer(sizer) sizer.Fit(panel) mainsizer = wx.BoxSizer(wx.HORIZONTAL) mainsizer.Add(panel, 0, wx.LEFT | wx.GROW | wx.ALL, 5) mainsizer.Add(self.image, 1, wx.CENTER | wx.GROW | wx.ALL, 5) self.SetSizer(mainsizer) mainsizer.Fit(self) self.SetAutoLayout(True) try: self.SetIcon(wx.Icon(ICON_FILE, wx.BITMAP_TYPE_ICO)) except: pass self.RefreshImage() wx.CallAfter(self.connect_pvs) def messag(self, s, panel=0): """write a message to the Status Bar""" wx.CallAfter(Closure(self.SetStatusText, text=s, number=panel)) # self.SetStatusText(s, panel) @EpicsFunction def unZoom(self, event=None, full=False): if self.zoom_lims is None or full: self.zoom_lims = [] if len(self.zoom_lims) == 0: xmin, ymin = 0, 0 width = self.ad_cam.MaxSizeX_RBV height = self.ad_cam.MaxSizeY_RBV self.zoom_lims = [] else: xmin, ymin, width, height = self.zoom_lims.pop() if (self.ad_cam.MinX == xmin and self.ad_cam.MinY == ymin and self.ad_cam.SizeX == width and self.ad_cam.SizeY == height): try: xmin, ymin, width, height = self.zoom_lims.pop() except: xmin, ymin = 0, 0 width = self.ad_cam.MaxSizeX_RBV height = self.ad_cam.MaxSizeY_RBV self.ad_cam.MinX = xmin self.ad_cam.MinY = ymin self.ad_cam.SizeX = width self.ad_cam.SizeY = height self.zoom_lims.append((xmin, ymin, width, height)) time.sleep(0.05) self.showZoomsize() if self.ad_cam.Acquire == 0 and self.im_size is not None: self.img_w = width self.img_h = height try: if self.colormode == 2: self.data.shape = [self.im_size[1], self.im_size[0], 3] zdata = self.data[ymin:ymin + height, xmin:xmin + width, :] else: self.data.shape = self.im_size[1], self.im_size[0] zdata = self.data[ymin:ymin + height, xmin:xmin + width] except ValueError: pass self.data = zdata #self.data.flatten() self.im_size = (width, height) # print zdata.shape, width, height, self.im_mode self.DatatoImage() # zdata, (width, height), self.im_mode) self.RefreshImage() self.image.Refresh() @EpicsFunction def onColor(self, event=None, item=None): if HAS_OVERLAY_DEVICE: color = event.GetValue() over = self.ad_overlays[item - 1] over.Red = color[0] over.Green = color[1] over.Blue = color[2] @EpicsFunction def showZoomsize(self): try: msg = 'Showing: %i x %i pixels' % (self.ad_cam.SizeX, self.ad_cam.SizeY) self.wids['zoomsize'].SetLabel(msg) except: pass @EpicsFunction def onZoom(self, x0, y0, x1, y1): width = self.ad_cam.SizeX height = self.ad_cam.SizeY xmin = max(0, int(self.ad_cam.MinX + x0 * width)) ymin = max(0, int(self.ad_cam.MinY + y0 * height)) width = int(x1 * width) height = int(y1 * height) if width < 2 or height < 2: return self.ad_cam.MinX = xmin self.ad_cam.MinY = ymin self.ad_cam.SizeX = width self.ad_cam.SizeY = height if self.zoom_lims is None: self.zoom_lims = [] self.zoom_lims.append((xmin, ymin, width, height)) time.sleep(0.05) self.showZoomsize() if self.ad_cam.Acquire == 0: self.img_w = width self.img_h = height if self.colormode == 2: self.data.shape = [self.im_size[1], self.im_size[0], 3] zdata = self.data[ymin:ymin + height, xmin:xmin + width, :] else: self.data.shape = self.im_size[1], self.im_size[0] zdata = self.data[ymin:ymin + height, xmin:xmin + width] self.data = zdata #. flatten() self.im_size = (width, height) self.DatatoImage() self.image.Refresh() def DatatoImage(self): #, data, size, mode): """convert raw data to image""" #x = debugtime() width, height = self.im_size d_size = (int(width * self.scale), int(height * self.scale)) data = self.data.flatten() #x.add('flatten') if self.imbuff is None or d_size != self.d_size or self.im_mode == 'L': try: self.imbuff = Image.frombuffer(self.im_mode, self.im_size, data, 'raw', self.im_mode, 0, 1) #x.add('made image') except: return self.d_size = d_size = (int(width * self.scale), int(height * self.scale)) if self.imbuff.size != d_size: self.imbuff = self.imbuff.resize(d_size) #x.add('resized imbuff') if self.wximage.GetSize() != self.imbuff.size: self.wximage = wx.EmptyImage(d_size[0], d_size[1]) #x.add('created wximage %s ' % (repr(self.wximage.GetSize()))) if self.im_mode == 'L': self.wximage.SetData(self.imbuff.convert('RGB').tostring()) elif self.im_mode == 'RGB': data.shape = (3, width, height) self.wximage = wx.ImageFromData(width, height, data) #x.add('set wx image wximage : %i, %i ' % d_size) self.image.SetValue(self.wximage) #x.add('set image value') #x.show() def onProfile(self, x0, y0, x1, y1): width = self.ad_cam.SizeX height = self.ad_cam.SizeY x0, y0 = int(x0 * width), int(y0 * height) x1, y1 = int(x1 * width), int(y1 * height) dx, dy = abs(x1 - x0), abs(y1 - y0) if dx < 2 and dy < 2: return outdat = [] if self.colormode == 2: self.data.shape = (self.im_size[1], self.im_size[0], 3) else: self.data.shape = self.im_size[1], self.im_size[0] if dy > dx: _y0 = min(int(y0), int(y1 + 0.5)) _y1 = max(int(y0), int(y1 + 0.5)) for iy in range(_y0, _y1): ix = int(x0 + (iy - int(y0)) * (x1 - x0) / (y1 - y0)) outdat.append((ix, iy)) else: _x0 = min(int(x0), int(x1 + 0.5)) _x1 = max(int(x0), int(x1 + 0.5)) for ix in range(_x0, _x1): iy = int(y0 + (ix - int(x0)) * (y1 - y0) / (x1 - x0)) outdat.append((ix, iy)) if self.lineplotter is None: self.lineplotter = PlotFrame(self, title='Image Profile') else: try: self.lineplotter.Raise() except PyDeadObjectError: self.lineplotter = PlotFrame(self, title='Image Profile') if self.colormode == 2: x, y, r, g, b = [], [], [], [], [] for ix, iy in outdat: x.append(ix) y.append(iy) r.append(self.data[iy, ix, 0]) g.append(self.data[iy, ix, 1]) b.append(self.data[iy, ix, 2]) xlabel = 'Pixel (x)' if dy > dx: x = y xlabel = 'Pixel (y)' self.lineplotter.plot(x, r, color='red', label='red', xlabel=xlabel, ylabel='Intensity', title='Image %i' % self.ad_cam.ArrayCounter_RBV) self.lineplotter.oplot(x, g, color='green', label='green') self.lineplotter.oplot(x, b, color='blue', label='blue') else: x, y, z = [], [], [] for ix, iy in outdat: x.append(ix) y.append(iy) z.append(self.data[iy, ix]) xlabel = 'Pixel (x)' if dy > dx: x = y xlabel = 'Pixel (y)' self.lineplotter.plot(x, z, color='k', xlabel=xlabel, ylabel='Intensity', title='Image %i' % self.ad_cam.ArrayCounter_RBV) self.lineplotter.Show() self.lineplotter.Raise() def onShowXY(self, xval, yval): ix = max(0, int(xval * self.ad_cam.SizeX)) iy = max(0, int(yval * self.ad_cam.SizeY)) if self.colormode == 2: self.data.shape = (self.im_size[1], self.im_size[0], 3) ival = tuple(self.data[iy, ix, :]) smsg = 'Pixel %i, %i, (R, G, B) = %s' % (ix, iy, repr(ival)) else: self.data.shape = self.im_size[1], self.im_size[0] ival = self.data[iy, ix] smsg = 'Pixel %i, %i, Intensity = %i' % (ix, iy, ival) self.messag(smsg, panel=1) def onName(self, evt=None, **kws): if evt is None: return s = evt.GetString() s = str(s).strip() if s.endswith(':image1:'): s = s[:-8] if s.endswith(':cam1:'): s = s[:-6] if s.endswith(':'): s = s[:-1] self.prefix = s self.connect_pvs() @EpicsFunction def onEntry(self, evt=None, key='name', **kw): if evt is None: return if key == 'start': self.n_img = 0 self.n_drawn = 0 self.starttime = time.time() self.imgcount_start = self.ad_cam.ArrayCounter_RBV self.ad_cam.Acquire = 1 elif key == 'stop': self.ad_cam.Acquire = 0 elif key == 'unzoom': self.unZoom() else: print 'unknown Entry ? ', key @EpicsFunction def connect_pvs(self, verbose=True): if self.prefix is None or len(self.prefix) < 2: return try: self.ad_cam.Acquire = 0 except: pass if self.prefix.endswith(':'): self.prefix = self.prefix[:-1] if self.prefix.endswith(':image1'): self.prefix = self.prefix[:-7] if self.prefix.endswith(':cam1'): self.prefix = self.prefix[:-5] if verbose: self.messag('Connecting to AD %s' % self.prefix) self.ad_img = epics.Device(self.prefix + ':image1:', delim='', attrs=self.img_attrs) self.ad_cam = epics.Device(self.prefix + ':cam1:', delim='', attrs=self.cam_attrs) self.ad_overlays = [] if HAS_OVERLAY_DEVICE: for ix in (1, 2): pvn = '%s:Over1:%i:' % (self.prefix, ix) self.ad_overlays.append(AD_OverlayPlugin(pvn)) time.sleep(0.010) if not self.ad_img.PV('UniqueId_RBV').connected: epics.poll() if not self.ad_img.PV('UniqueId_RBV').connected: self.messag('Warning: Camera seems to not be connected!') return if verbose: self.messag('Connected to AD %s' % self.prefix) self.SetTitle("Epics Image Display: %s" % self.prefix) self.wids['color'].SetPV(self.ad_cam.PV('ColorMode')) self.wids['exptime'].SetPV(self.ad_cam.PV('AcquireTime')) self.wids['period'].SetPV(self.ad_cam.PV('AcquirePeriod')) self.wids['gain'].SetPV(self.ad_cam.PV('Gain')) self.wids['numimages'].SetPV(self.ad_cam.PV('NumImages')) self.wids['imagemode'].SetPV(self.ad_cam.PV('ImageMode')) self.wids['triggermode'].SetPV(self.ad_cam.PV('TriggerMode')) sizex = self.ad_cam.MaxSizeX_RBV sizey = self.ad_cam.MaxSizeY_RBV if HAS_OVERLAY_DEVICE: over = self.ad_overlays[0] c1 = (over.Red, over.Green, over.Blue) self.wids['o1color'].SetColour(hexcolor(c1)) self.wids['o1posx'].SetPV(over.PV('PositionX')) self.wids['o1posx'].SetMax(sizex) self.wids['o1posy'].SetPV(over.PV('PositionY')) self.wids['o1posy'].SetMax(sizey) self.wids['o1sizx'].SetPV(over.PV('SizeX')) self.wids['o1sizx'].SetMax(sizex) self.wids['o1sizy'].SetPV(over.PV('SizeY')) self.wids['o1sizy'].SetMax(sizey) self.wids['o1shape'].SetPV(over.PV('Shape')) self.wids['o1name'].SetPV(over.PV('Name')) self.wids['o1use'].SetPV(over.PV('Use')) over = self.ad_overlays[1] c1 = (over.Red, over.Green, over.Blue) self.wids['o2color'].SetColour(hexcolor(c1)) self.wids['o2posx'].SetPV(over.PV('PositionX')) self.wids['o2posx'].SetMax(sizex) self.wids['o2posy'].SetPV(over.PV('PositionY')) self.wids['o2posy'].SetMax(sizey) self.wids['o2sizx'].SetPV(over.PV('SizeX')) self.wids['o2sizx'].SetMax(sizex) self.wids['o2sizy'].SetPV(over.PV('SizeY')) self.wids['o2sizy'].SetMax(sizey) self.wids['o2shape'].SetPV(over.PV('Shape')) self.wids['o2name'].SetPV(over.PV('Name')) self.wids['o2use'].SetPV(over.PV('Use')) sizelabel = 'Image Size: %i x %i pixels' try: sizelabel = sizelabel % (sizex, sizey) except: sizelabel = sizelabel % (0, 0) self.wids['fullsize'].SetLabel(sizelabel) self.showZoomsize() self.ad_img.add_callback('ArrayCounter_RBV', self.onNewImage) self.ad_img.add_callback('ArraySize0_RBV', self.onProperty, dim=0) self.ad_img.add_callback('ArraySize1_RBV', self.onProperty, dim=1) self.ad_img.add_callback('ArraySize2_RBV', self.onProperty, dim=2) self.ad_img.add_callback('ColorMode_RBV', self.onProperty, dim='color') self.ad_cam.add_callback('DetectorState_RBV', self.onDetState) epics.caput("%s:cam1:ArrayCallbacks" % self.prefix, 1) for p in self.enabled_plugins: epics.caput("%s:%s:EnableCallbacks" % (self.prefix, p), 1) epics.caput("%s:JPEG1:NDArrayPort" % self.prefix, "OVER1") epics.caput("%s:TIFF1:NDArrayPort" % self.prefix, "OVER1") epics.caput("%s:image1:NDArrayPort" % self.prefix, "OVER1") self.ad_cam.Acquire = 1 self.GetImageSize() self.unZoom() epics.poll() self.RefreshImage() @EpicsFunction def GetImageSize(self): self.arrsize = [1, 1, 1] self.arrsize[0] = self.ad_img.ArraySize0_RBV self.arrsize[1] = self.ad_img.ArraySize1_RBV self.arrsize[2] = self.ad_img.ArraySize2_RBV self.colormode = self.ad_img.ColorMode_RBV self.img_w = self.arrsize[1] self.img_h = self.arrsize[0] if self.colormode == 2: self.img_w = self.arrsize[2] self.img_h = self.arrsize[1] @DelayedEpicsCallback def onDetState(self, pvname=None, value=None, char_value=None, **kw): self.messag(char_value, panel=1) @DelayedEpicsCallback def onProperty(self, pvname=None, value=None, dim=None, **kw): if dim == 'color': self.colormode = value else: self.arrsize[dim] = value @DelayedEpicsCallback def onNewImage(self, pvname=None, value=None, **kw): if value != self.img_id: self.img_id = value if not self.drawing: self.drawing = True self.RefreshImage() @EpicsFunction def RefreshImage(self, pvname=None, **kws): try: wx.Yield() except: pass d = debugtime() if self.ad_img is None or self.ad_cam is None: return imgdim = self.ad_img.NDimensions_RBV imgcount = self.ad_cam.ArrayCounter_RBV now = time.time() if (imgcount == self.imgcount or abs(now - self.last_update) < 0.025): self.drawing = False return d.add('refresh img start') self.imgcount = imgcount self.drawing = True self.n_drawn += 1 self.n_img = imgcount - self.imgcount_start #print 'ImgCount, n_drawn: ', imgcount, self.n_img, self.n_drawn self.last_update = time.time() self.image.can_resize = False xmin = self.ad_cam.MinX ymin = self.ad_cam.MinY width = self.ad_cam.SizeX height = self.ad_cam.SizeY arraysize = self.arrsize[0] * self.arrsize[1] if imgdim == 3: arraysize = arraysize * self.arrsize[2] if not self.ad_img.PV('ArrayData').connected: self.drawing = False return d.add('refresh img before raw get %i' % arraysize) rawdata = self.ad_img.PV('ArrayData').get(count=arraysize) d.add('refresh img after raw get') im_mode = 'L' im_size = (self.arrsize[0], self.arrsize[1]) if self.colormode == 2: im_mode = 'RGB' im_size = [self.arrsize[1], self.arrsize[2]] if (self.colormode == 0 and isinstance(rawdata, np.ndarray) and rawdata.dtype != np.uint8): im_mode = 'I' rawdata = rawdata.astype(np.uint32) d.add('refresh img before msg') self.messag(' Image # %i ' % self.ad_cam.ArrayCounter_RBV, panel=2) d.add('refresh img before get image size') self.GetImageSize() self.im_size = im_size self.im_mode = im_mode self.data = rawdata d.add('refresh img before data to image') self.DatatoImage() d.add('refresh img after data to image') self.image.can_resize = True nmissed = max(0, self.n_img - self.n_drawn) delt = time.time() - self.starttime percent_drawn = self.n_drawn * 100 / (self.n_drawn + nmissed) smsg = self.stat_msg % (percent_drawn, self.n_drawn / delt) self.messag(smsg, panel=0) self.drawing = False d.add('refresh img done')
class TestFrame(wx.Frame): def __init__(self, parent=None, *args, **kwds): kwds["style"] = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.TAB_TRAVERSAL wx.Frame.__init__(self, parent, wx.NewId(), "", wx.DefaultPosition, wx.Size(-1, -1), **kwds) self.SetTitle(" WXMPlot Plotting Demo") self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False)) menu = wx.Menu() ID_EXIT = wx.NewId() menu_exit = menu.Append(ID_EXIT, "E&xit", "Terminate the program") menuBar = wx.MenuBar() menuBar.Append(menu, "&File") self.SetMenuBar(menuBar) self.Bind(wx.EVT_MENU, self.OnExit, menu_exit) self.Bind(wx.EVT_CLOSE, self.OnExit) # CloseEvent) self.plotframe = None self.create_data() framesizer = wx.BoxSizer(wx.VERTICAL) panel = wx.Panel(self, -1, size=(-1, -1)) panelsizer = wx.BoxSizer(wx.VERTICAL) panelsizer.Add( wx.StaticText(panel, -1, "wxmplot 2D PlotPanel examples "), 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT | wx.EXPAND, 10, ) b10 = wx.Button(panel, -1, "Example #1", size=(-1, -1)) b20 = wx.Button(panel, -1, "Example #2", size=(-1, -1)) b22 = wx.Button(panel, -1, "Plot with 2 axes", size=(-1, -1)) b31 = wx.Button(panel, -1, "Plot with Errorbars", size=(-1, -1)) b32 = wx.Button(panel, -1, "SemiLog Plot", size=(-1, -1)) b40 = wx.Button(panel, -1, "Start Timed Plot", size=(-1, -1)) b50 = wx.Button(panel, -1, "Stop Timed Plot", size=(-1, -1)) b60 = wx.Button(panel, -1, "Plot 500,000 points", size=(-1, -1)) b10.Bind(wx.EVT_BUTTON, self.onPlot1) b20.Bind(wx.EVT_BUTTON, self.onPlot2) b22.Bind(wx.EVT_BUTTON, self.onPlot2Axes) b31.Bind(wx.EVT_BUTTON, self.onPlotErr) b32.Bind(wx.EVT_BUTTON, self.onPlotSLog) b40.Bind(wx.EVT_BUTTON, self.onStartTimer) b50.Bind(wx.EVT_BUTTON, self.onStopTimer) b60.Bind(wx.EVT_BUTTON, self.onPlotBig) panelsizer.Add(b10, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b20, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b22, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b31, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b32, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b40, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b50, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b60, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panel.SetSizer(panelsizer) panelsizer.Fit(panel) framesizer.Add(panel, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.EXPAND, 2) self.SetSizer(framesizer) framesizer.Fit(self) self.Bind(wx.EVT_TIMER, self.onTimer) self.timer = wx.Timer(self) self.Refresh() def create_data(self): self.count = 0 self.x = x = arange(0.0, 25.0, 0.1) self.y1 = 4 * cos(2 * pi * (x - 1) / 5.7) / (6 + x) + 2 * sin(2 * pi * (x - 1) / 2.2) / (10) self.y2 = sin(2 * pi * x / 30.0) self.y3 = -pi + 2 * (x / 10.0 + exp(-(x - 3) / 5.0)) self.y4 = exp(0.01 + 0.5 * x) / (x + 2) self.y5 = 3000 * self.y3 self.npts = len(self.x) self.bigx = linspace(0, 2500, 500000) self.bigy = sin(pi * self.bigx / 140.0) + cos(pi * self.bigx / 277.0) + cos(pi * self.bigx / 820.0) def ShowPlotFrame(self, do_raise=True, clear=True): "make sure plot frame is enabled, and visible" if self.plotframe is None: self.plotframe = PlotFrame(self) self.has_plot = False try: self.plotframe.Show() except PyDeadObjectError: self.plotframe = PlotFrame(self) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config() def onPlot1(self, event=None): self.ShowPlotFrame() self.plotframe.plot(self.x, self.y1) self.plotframe.oplot(self.x, self.y2) self.plotframe.write_message("Plot 1") def onPlot2(self, event=None): self.ShowPlotFrame() x = arange(100) y1 = cos(pi * x / 72) y2 = sin(pi * x / 23) self.plotframe.plot(x, y1, color="red") self.plotframe.oplot(x, y2, color="green3", marker="+") self.plotframe.write_message("Plot 2") def onPlotErr(self, event=None): self.ShowPlotFrame() npts = 81 x = linspace(0, 40.0, npts) y = 0.4 * cos(x / 2.0) + random.normal(scale=0.03, size=npts) dy = 0.03 * (ones(npts) + random.normal(scale=0.2, size=npts)) self.plotframe.plot( x, y, dy=dy, color="red", linewidth=0, xlabel="x", ylabel="y", marker="o", title="Plot with error bars" ) self.plotframe.write_message("Errorbars!") def onPlot2Axes(self, event=None): self.ShowPlotFrame() self.plotframe.plot(self.x, self.y2, color="black", style="dashed") self.plotframe.oplot(self.x, self.y5, color="red", side="right") self.plotframe.write_message("Plot with 2 axes") def onPlotSLog(self, event=None): self.ShowPlotFrame() self.plotframe.plot(self.x, self.y4, ylog_scale=True, color="black", style="dashed") self.plotframe.write_message("Semi Log Plot") def onPlotBig(self, event=None): self.ShowPlotFrame() t0 = time.time() self.plotframe.plot(self.bigx, self.bigy, marker="+", linewidth=0) dt = time.time() - t0 self.plotframe.write_message("Plot array with npts=%i, elapsed time=%8.3f s" % (len(self.bigx), dt)) def report_memory(i): pid = os.getpid() if os.name == "posix": mem = os.popen("ps -o rss -p %i" % pid).readlines()[1].split()[0] else: mem = 0 return int(mem) def onStartTimer(self, event=None): self.count = 0 self.up_count = 0 self.n_update = 1 self.datrange = None self.time0 = time.time() self.start_mem = self.report_memory() self.timer.Start(10) def timer_results(self): if self.count < 2: return etime = time.time() - self.time0 tpp = etime / max(1, self.count) s = "drew %i points in %8.3f s: time/point= %8.4f s" % (self.count, etime, tpp) self.plotframe.write_message(s) self.time0 = 0 self.count = 0 self.datrange = None def onStopTimer(self, event=None): self.timer.Stop() try: self.timer_results() except: pass def onTimer(self, event): # print 'timer ', self.count, time.time() self.count += 1 self.ShowPlotFrame(do_raise=False, clear=False) n = self.count if n < 2: return if n >= self.npts: self.timer.Stop() self.timer_results() elif n <= 3: self.plotframe.plot(self.x[:n], self.y1[:n]) # , grid=False) else: self.plotframe.update_line(0, self.x[:n], self.y1[:n], update_limits=n < 10, draw=True) etime = time.time() - self.time0 s = " %i / %i points in %8.4f s" % (n, self.npts, etime) self.plotframe.write_message(s) if self.datrange is None: self.datrange = [min(self.x[:n]), max(self.x[:n]), min(self.y1[:n]), max(self.y1[:n])] dr = [min(self.x[:n]), max(self.x[:n]), min(self.y1[:n]), max(self.y1[:n])] lims = self.plotframe.panel.get_viewlimits() if dr[0] < lims[0] or dr[1] > lims[1] or dr[2] < lims[2] or dr[3] > lims[3]: self.datrange = dr if n < len(self.x): nmax = min(int(n * 1.6), len(self.x) - 1) self.datrange[1] = self.x[nmax] self.plotframe.panel.set_xylims(self.datrange) # if (n > self.n_update-1) or # (xr[0] < xv[0]) or (xr[1] > xv[1]) or # (yr[0] < yv[0]) or (yr[1] > yv[1])): # nx = self.n_update = min(self.npts,3+int(self.n_update*2.0)) # if nx > int(0.92*self.npts): # nx = self.n_update = self.npts # xylims = (min(self.x),max(self.x), # min(self.y1),max(self.y1)) # else: # xylims = (min(self.x[0:nx]),max(self.x[0:nx]), # min(self.y1[0:nx]),max(self.y1[0:nx])) # self.up_count = self.up_count + 1 # self.plotframe.panel.set_xylims(xylims) def OnAbout(self, event): dlg = wx.MessageDialog( self, "This sample program shows some\n" "examples of MPlot PlotFrame.\n" "message dialog.", "About MPlot test", wx.OK | wx.ICON_INFORMATION, ) dlg.ShowModal() dlg.Destroy() def OnExit(self, event): try: if self.plotframe != None: self.plotframe.onExit() except: pass self.Destroy()
class ADFrame(wx.Frame): """ AreaDetector Display Frame """ def __init__(self, configfile=None): wx.Frame.__init__(self, None, -1, 'AreaDetector Viewer', style=wx.DEFAULT_FRAME_STYLE) if configfile is None: wcard = 'Detector Config Files (*.yaml)|*.yaml|All files (*.*)|*.*' configfile = FileOpen(self, "Read Detector Configuration File", default_file='det.yaml', wildcard=wcard) if configfile is None: sys.exit() self.config = read_adconfig(configfile) self.prefix = self.config['general']['prefix'] self.fname = self.config['general']['name'] self.colormode = self.config['general']['colormode'].lower() self.cam_attrs = self.config['cam_attributes'] self.img_attrs = self.config['img_attributes'] self.fsaver = self.config['general']['filesaver'] self.SetTitle(self.config['general']['title']) self.scandb = None if ScanDB is not None: self.scandb = ScanDB() if self.scandb.engine is None: # not connected to running scandb server self.scandb = None self.calib = None self.ad_img = None self.ad_cam = None self.lineplotter = None self.integrator = None self.int_panel = None self.int_lastid = None self.contrast_levels = None self.thumbnail = None self.buildMenus() self.buildFrame() def buildFrame(self): self.SetFont(Font(11)) sbar = self.CreateStatusBar(3, wx.CAPTION) self.SetStatusWidths([-1, -1, -1]) self.SetStatusText('', 0) sizer = wx.GridBagSizer(3, 3) panel = self.panel = wx.Panel(self) pvpanel = PVConfigPanel(panel, self.prefix, self.config['controls']) wsize = (100, -1) lsize = (250, -1) start_btn = wx.Button(panel, label='Start', size=wsize) stop_btn = wx.Button(panel, label='Stop', size=wsize) start_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='start')) stop_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='stop')) self.contrast = ContrastControl(panel, callback=self.set_contrast_level) self.imagesize = wx.StaticText(panel, label='? x ?', size=(150, 30), style=txtstyle) def lin(len=200, wid=2, style=wx.LI_HORIZONTAL): return wx.StaticLine(panel, size=(len, wid), style=style) irow = 0 sizer.Add(pvpanel, (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(start_btn, (irow, 0), (1, 1), labstyle) sizer.Add(stop_btn, (irow, 1), (1, 1), labstyle) if self.config['general'].get('show_free_run', False): free_btn = wx.Button(panel, label='Free Run', size=wsize) free_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='free')) irow += 1 sizer.Add(free_btn, (irow, 0), (1, 2), labstyle) irow += 1 sizer.Add(lin(200, wid=4), (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(self.imagesize, (irow, 0), (1, 3), labstyle) if self.colormode.startswith('mono'): self.cmap_choice = wx.Choice(panel, size=(80, -1), choices=self.config['colormaps']) self.cmap_choice.SetSelection(0) self.cmap_choice.Bind(wx.EVT_CHOICE, self.onColorMap) self.cmap_reverse = wx.CheckBox(panel, label='Reverse', size=(60, -1)) self.cmap_reverse.Bind(wx.EVT_CHECKBOX, self.onColorMap) irow += 1 sizer.Add(wx.StaticText(panel, label='Color Map: '), (irow, 0), (1, 1), labstyle) sizer.Add(self.cmap_choice, (irow, 1), (1, 1), labstyle) sizer.Add(self.cmap_reverse, (irow, 2), (1, 1), labstyle) irow += 1 sizer.Add(self.contrast.label, (irow, 0), (1, 1), labstyle) sizer.Add(self.contrast.choice, (irow, 1), (1, 1), labstyle) if self.config['general']['show_1dintegration']: self.show1d_btn = wx.Button(panel, label='Show 1D Integration', size=(200, -1)) self.show1d_btn.Bind(wx.EVT_BUTTON, self.onShowIntegration) self.show1d_btn.Disable() irow += 1 sizer.Add(self.show1d_btn, (irow, 0), (1, 2), labstyle) if self.config['general']['show_thumbnail']: t_size = self.config['general'].get('thumbnail_size', 100) self.thumbnail = ThumbNailImagePanel(panel, imgsize=t_size, size=(350, 350), motion_writer=partial( self.write, panel=0)) label = wx.StaticText(panel, label='Thumbnail size (pixels): ', size=(200, -1), style=txtstyle) self.thumbsize = FloatSpin(panel, value=100, min_val=10, increment=5, action=self.onThumbSize, size=(150, -1), style=txtstyle) irow += 1 sizer.Add(label, (irow, 0), (1, 1), labstyle) sizer.Add(self.thumbsize, (irow, 1), (1, 1), labstyle) irow += 1 sizer.Add(self.thumbnail, (irow, 0), (1, 2), labstyle) panel.SetSizer(sizer) sizer.Fit(panel) # image panel self.image = ADMonoImagePanel( self, prefix=self.prefix, rot90=self.config['general']['default_rotation'], size=(750, 750), writer=partial(self.write, panel=1), thumbnail=self.thumbnail, motion_writer=partial(self.write, panel=2)) mainsizer = wx.BoxSizer(wx.HORIZONTAL) mainsizer.Add(panel, 0, wx.LEFT | wx.GROW | wx.ALL) mainsizer.Add(self.image, 1, wx.CENTER | wx.GROW | wx.ALL) self.SetSizer(mainsizer) mainsizer.Fit(self) self.SetAutoLayout(True) iconfile = self.config['general'].get('iconfile', None) if iconfile is None or not os.path.exists(iconfile): iconfile = DEFAULT_ICONFILE try: self.SetIcon(wx.Icon(iconfile, wx.BITMAP_TYPE_ICO)) except: pass self.connect_pvs() def onThumbSize(self, event=None): self.thumbnail.imgsize = int(self.thumbsize.GetValue()) def onColorMap(self, event=None): cmap_name = self.cmap_choice.GetStringSelection() if self.cmap_reverse.IsChecked(): cmap_name = cmap_name + '_r' self.image.colormap = getattr(colormap, cmap_name) self.image.Refresh() def onCopyImage(self, event=None): "copy bitmap of canvas to system clipboard" bmp = wx.BitmapDataObject() bmp.SetBitmap(wx.Bitmap(self.image.GrabWxImage())) wx.TheClipboard.Open() wx.TheClipboard.SetData(bmp) wx.TheClipboard.Close() wx.TheClipboard.Flush() def onReadCalibFile(self, event=None): "read calibration file" wcards = "Poni Files(*.poni)|*.poni|All files (*.*)|*.*" dlg = wx.FileDialog(None, message='Read Calibration File', defaultDir=os.getcwd(), wildcard=wcards, style=wx.FD_OPEN) ppath = None if dlg.ShowModal() == wx.ID_OK: ppath = os.path.abspath(dlg.GetPath()) if os.path.exists(ppath): self.setup_calibration(ppath) def setup_calibration(self, ponifile): """set up calibration from PONI file""" calib = read_poni(ponifile) # if self.image.rot90 in (1, 3): # calib['rot3'] = np.pi/2.0 self.calib = calib if HAS_PYFAI: self.integrator = AzimuthalIntegrator(**calib) self.show1d_btn.Enable() else: self.write('Warning: PyFAI is not installed') if self.scandb is not None: _, calname = os.path.split(ponifile) self.scandb.set_detectorconfig(calname, json.dumps(calib)) self.scandb.set_info('xrd_calibration', calname) def onShowIntegration(self, event=None): if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() def onAutoIntegration(self, event=None): if not event.IsChecked(): self.int_timer.Stop() return if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() self.int_timer.Start(500) def show_1dpattern(self, init=False): if self.calib is None or not HAS_PYFAI: return img = self.ad_img.PV('ArrayData').get() h, w = self.image.GetImageSize() img.shape = (w, h) # may need to trim outer pixels (int1d_trimx/int1d_trimy in config) xstride = 1 if self.config['general'].get('int1d_flipx', False): xstride = -1 xslice = slice(None, None, xstride) trimx = int(self.config['general'].get('int1d_trimx', 0)) if trimx != 0: xslice = slice(trimx * xstride, -trimx * xstride, xstride) ystride = 1 if self.config['general'].get('int1d_flipy', True): ystride = -1 yslice = slice(None, None, ystride) trimy = int(self.config['general'].get('int1d_trimy', 0)) if trimy > 0: yslice = slice(trimy * ystride, -trimy * ystride, ystride) img = img[yslice, xslice] img_id = self.ad_cam.ArrayCounter_RBV q, xi = self.integrator.integrate1d(img, 2048, unit='q_A^-1', correctSolidAngle=True, polarization_factor=0.999) if init: self.int_panel.plot(q, xi, xlabel=r'$Q (\rm\AA^{-1})$', marker='+', title='Image %d' % img_id) self.int_panel.Raise() self.int_panel.Show() else: self.int_panel.update_line(0, q, xi, draw=True) self.int_panel.set_title('Image %d' % img_id) @EpicsFunction def onSaveImage(self, event=None): "prompts for and save image to file" defdir = os.getcwd() self.fname = "Image_%i.tiff" % self.ad_cam.ArrayCounter_RBV dlg = wx.FileDialog(None, message='Save Image as', defaultDir=os.getcwd(), defaultFile=self.fname, style=wx.FD_SAVE) path = None if dlg.ShowModal() == wx.ID_OK: path = os.path.abspath(dlg.GetPath()) root, fname = os.path.split(path) epics.caput("%s%sFileName" % self.prefix, self.fsaver, fname) epics.caput("%s%sFileWriteMode" % self.prefix, self.fsaver, 0) time.sleep(0.05) epics.caput("%s%sWriteFile" % self.prefix, self.fsaver, 1) time.sleep(0.05) file_pv = "%s%sFullFileName_RBV" % (self.prefix, self.prefix) print("Saved image File ", epics.caget(file_pv, as_string=True)) def onExit(self, event=None): try: wx.Yield() except: pass self.Destroy() def onAbout(self, event=None): msg = """areaDetector Display version 0.2 Matt Newville <*****@*****.**>""" dlg = wx.MessageDialog(self, msg, "About areaDetector Display", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def buildMenus(self): fmenu = wx.Menu() MenuItem(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage) MenuItem(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard", self.onCopyImage) MenuItem(self, fmenu, "Read Calibration File", "Read PONI Calibration", self.onReadCalibFile) fmenu.AppendSeparator() MenuItem(self, fmenu, "E&xit\tCtrl+Q", "Exit Program", self.onExit) omenu = wx.Menu() MenuItem(self, omenu, "&Rotate CCW\tCtrl+R", "Rotate Counter Clockwise", self.onRot90) MenuItem(self, omenu, "Flip Up/Down\tCtrl+T", "Flip Up/Down", self.onFlipV) MenuItem(self, omenu, "Flip Left/Right\tCtrl+F", "Flip Left/Right", self.onFlipH) MenuItem(self, omenu, "Reset Rotations and Flips", "Reset", self.onResetRotFlips) omenu.AppendSeparator() hmenu = wx.Menu() MenuItem(self, hmenu, "About", "About areaDetector Display", self.onAbout) mbar = wx.MenuBar() mbar.Append(fmenu, "File") mbar.Append(omenu, "Options") mbar.Append(hmenu, "&Help") self.SetMenuBar(mbar) def onResetRotFlips(self, event): self.image.rot90 = 0 self.image.flipv = self.image.fliph = False def onRot90(self, event): self.image.rot90 = (self.image.rot90 - 1) % 4 def onFlipV(self, event): self.image.flipv = not self.image.flipv def onFlipH(self, event): self.image.fliph = not self.image.fliph def set_contrast_level(self, contrast_level=0): self.image.contrast_levels = [contrast_level, 100.0 - contrast_level] self.image.Refresh() def write(self, s, panel=0): """write a message to the Status Bar""" self.SetStatusText(text=s, number=panel) @EpicsFunction def onButton(self, event=None, key='free'): key = key.lower() if key.startswith('free'): ftime = self.config['general']['free_run_time'] self.image.restart_fps_counter() self.ad_cam.AcquireTime = ftime self.ad_cam.AcquirePeriod = ftime self.ad_cam.NumImages = int((3 * 86400.) / ftime) self.ad_cam.Acquire = 1 elif key.startswith('start'): self.image.restart_fps_counter() self.ad_cam.Acquire = 1 elif key.startswith('stop'): self.ad_cam.Acquire = 0 @EpicsFunction def connect_pvs(self, verbose=True): if self.prefix is None or len(self.prefix) < 2: return self.write('Connecting to areaDetector %s' % self.prefix) self.ad_img = epics.Device(self.prefix + 'image1:', delim='', attrs=self.img_attrs) self.ad_cam = epics.Device(self.prefix + 'cam1:', delim='', attrs=self.cam_attrs) if self.config['general']['use_filesaver']: epics.caput("%s%sEnableCallbacks" % (self.prefix, self.fsaver), 1) epics.caput("%s%sAutoSave" % (self.prefix, self.fsaver), 0) epics.caput("%s%sAutoIncrement" % (self.prefix, self.fsaver), 0) epics.caput("%s%sFileWriteMode" % (self.prefix, self.fsaver), 0) time.sleep(0.002) if not self.ad_img.PV('UniqueId_RBV').connected: epics.poll() if not self.ad_img.PV('UniqueId_RBV').connected: self.write('Warning: detector seems to not be connected!') return if verbose: self.write('Connected to detector %s' % self.prefix) self.SetTitle("Epics areaDetector Display: %s" % self.prefix) sizex = self.ad_cam.MaxSizeX_RBV sizey = self.ad_cam.MaxSizeY_RBV sizelabel = 'Image Size: %i x %i pixels' try: sizelabel = sizelabel % (sizex, sizey) except: sizelabel = sizelabel % (0, 0) self.imagesize.SetLabel(sizelabel) self.ad_cam.add_callback('DetectorState_RBV', self.onDetState) self.contrast.set_level_str('0.01') @DelayedEpicsCallback def onDetState(self, pvname=None, value=None, char_value=None, **kw): self.write(char_value, panel=0)
class ADFrame(wx.Frame): """ AreaDetector Display Frame """ def __init__(self, configfile=None): wx.Frame.__init__(self, None, -1, 'AreaDetector Viewer', style=wx.DEFAULT_FRAME_STYLE) if configfile is None: wcard = 'Detector Config Files (*.yaml)|*.yaml|All files (*.*)|*.*' configfile = FileOpen(self, "Read Detector Configuration File", default_file='det.yaml', wildcard=wcard) if configfile is None: sys.exit() self.config = read_adconfig(configfile) self.prefix = self.config['general']['prefix'] self.fname = self.config['general']['name'] self.colormode = self.config['general']['colormode'].lower() self.cam_attrs = self.config['cam_attributes'] self.img_attrs = self.config['img_attributes'] self.fsaver = self.config['general']['filesaver'] self.SetTitle(self.config['general']['title']) self.scandb = None if ScanDB is not None: self.scandb = ScanDB() if self.scandb.engine is None: # not connected to running scandb server self.scandb = None self.calib = None self.ad_img = None self.ad_cam = None self.lineplotter = None self.integrator = None self.int_panel = None self.int_lastid = None self.contrast_levels = None self.thumbnail = None self.buildMenus() self.buildFrame() def buildFrame(self): self.SetFont(Font(11)) sbar = self.CreateStatusBar(3, wx.CAPTION) self.SetStatusWidths([-1, -1, -1]) self.SetStatusText('',0) sizer = wx.GridBagSizer(3, 3) panel = self.panel = wx.Panel(self) pvpanel = PVConfigPanel(panel, self.prefix, self.config['controls']) wsize = (100, -1) lsize = (250, -1) start_btn = wx.Button(panel, label='Start', size=wsize) stop_btn = wx.Button(panel, label='Stop', size=wsize) start_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='start')) stop_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='stop')) self.contrast = ContrastControl(panel, callback=self.set_contrast_level) self.imagesize = wx.StaticText(panel, label='? x ?', size=(150, 30), style=txtstyle) def lin(len=200, wid=2, style=wx.LI_HORIZONTAL): return wx.StaticLine(panel, size=(len, wid), style=style) irow = 0 sizer.Add(pvpanel, (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(start_btn, (irow, 0), (1, 1), labstyle) sizer.Add(stop_btn, (irow, 1), (1, 1), labstyle) if self.config['general'].get('show_free_run', False): free_btn = wx.Button(panel, label='Free Run', size=wsize) free_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='free')) irow += 1 sizer.Add(free_btn, (irow, 0), (1, 2), labstyle) irow += 1 sizer.Add(lin(200, wid=4), (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(self.imagesize, (irow, 0), (1, 3), labstyle) if self.colormode.startswith('mono'): self.cmap_choice = wx.Choice(panel, size=(80, -1), choices=self.config['colormaps']) self.cmap_choice.SetSelection(0) self.cmap_choice.Bind(wx.EVT_CHOICE, self.onColorMap) self.cmap_reverse = wx.CheckBox(panel, label='Reverse', size=(60, -1)) self.cmap_reverse.Bind(wx.EVT_CHECKBOX, self.onColorMap) irow += 1 sizer.Add(wx.StaticText(panel, label='Color Map: '), (irow, 0), (1, 1), labstyle) sizer.Add(self.cmap_choice, (irow, 1), (1, 1), labstyle) sizer.Add(self.cmap_reverse, (irow, 2), (1, 1), labstyle) irow += 1 sizer.Add(self.contrast.label, (irow, 0), (1, 1), labstyle) sizer.Add(self.contrast.choice, (irow, 1), (1, 1), labstyle) if self.config['general']['show_1dintegration']: self.show1d_btn = wx.Button(panel, label='Show 1D Integration', size=(200, -1)) self.show1d_btn.Bind(wx.EVT_BUTTON, self.onShowIntegration) self.show1d_btn.Disable() irow += 1 sizer.Add(self.show1d_btn, (irow, 0), (1, 2), labstyle) if self.config['general']['show_thumbnail']: t_size=self.config['general'].get('thumbnail_size', 100) self.thumbnail = ThumbNailImagePanel(panel, imgsize=t_size, size=(350, 350), motion_writer=partial(self.write, panel=0)) label = wx.StaticText(panel, label='Thumbnail size (pixels): ', size=(200, -1), style=txtstyle) self.thumbsize = FloatSpin(panel, value=100, min_val=10, increment=5, action=self.onThumbSize, size=(150, -1), style=txtstyle) irow += 1 sizer.Add(label, (irow, 0), (1, 1), labstyle) sizer.Add(self.thumbsize, (irow, 1), (1, 1), labstyle) irow += 1 sizer.Add(self.thumbnail, (irow, 0), (1, 2), labstyle) panel.SetSizer(sizer) sizer.Fit(panel) # image panel self.image = ADMonoImagePanel(self, prefix=self.prefix, rot90=self.config['general']['default_rotation'], size=(750, 750), writer=partial(self.write, panel=1), thumbnail=self.thumbnail, motion_writer=partial(self.write, panel=2)) mainsizer = wx.BoxSizer(wx.HORIZONTAL) mainsizer.Add(panel, 0, wx.LEFT|wx.GROW|wx.ALL) mainsizer.Add(self.image, 1, wx.CENTER|wx.GROW|wx.ALL) self.SetSizer(mainsizer) mainsizer.Fit(self) self.SetAutoLayout(True) iconfile = self.config['general'].get('iconfile', None) if iconfile is None or not os.path.exists(iconfile): iconfile = DEFAULT_ICONFILE try: self.SetIcon(wx.Icon(iconfile, wx.BITMAP_TYPE_ICO)) except: pass self.connect_pvs() def onThumbSize(self, event=None): self.thumbnail.imgsize = int(self.thumbsize.GetValue()) def onColorMap(self, event=None): cmap_name = self.cmap_choice.GetStringSelection() if self.cmap_reverse.IsChecked(): cmap_name = cmap_name + '_r' self.image.colormap = getattr(colormap, cmap_name) self.image.Refresh() def onCopyImage(self, event=None): "copy bitmap of canvas to system clipboard" bmp = wx.BitmapDataObject() bmp.SetBitmap(wx.Bitmap(self.image.GrabWxImage())) wx.TheClipboard.Open() wx.TheClipboard.SetData(bmp) wx.TheClipboard.Close() wx.TheClipboard.Flush() def onReadCalibFile(self, event=None): "read calibration file" wcards = "Poni Files(*.poni)|*.poni|All files (*.*)|*.*" dlg = wx.FileDialog(None, message='Read Calibration File', defaultDir=os.getcwd(), wildcard=wcards, style=wx.FD_OPEN) ppath = None if dlg.ShowModal() == wx.ID_OK: ppath = os.path.abspath(dlg.GetPath()) if os.path.exists(ppath): self.setup_calibration(ppath) def setup_calibration(self, ponifile): """set up calibration from PONI file""" calib = read_poni(ponifile) # if self.image.rot90 in (1, 3): # calib['rot3'] = np.pi/2.0 self.calib = calib if HAS_PYFAI: self.integrator = AzimuthalIntegrator(**calib) self.show1d_btn.Enable() else: self.write('Warning: PyFAI is not installed') if self.scandb is not None: _, calname = os.path.split(ponifile) self.scandb.set_detectorconfig(calname, json.dumps(calib)) self.scandb.set_info('xrd_calibration', calname) def onShowIntegration(self, event=None): if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() def onAutoIntegration(self, event=None): if not event.IsChecked(): self.int_timer.Stop() return if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() self.int_timer.Start(500) def show_1dpattern(self, init=False): if self.calib is None or not HAS_PYFAI: return img = self.ad_img.PV('ArrayData').get() h, w = self.image.GetImageSize() img.shape = (w, h) # may need to trim outer pixels (int1d_trimx/int1d_trimy in config) xstride = 1 if self.config['general'].get('int1d_flipx', False): xstride = -1 xslice = slice(None, None, xstride) trimx = int(self.config['general'].get('int1d_trimx', 0)) if trimx != 0: xslice = slice(trimx*xstride, -trimx*xstride, xstride) ystride = 1 if self.config['general'].get('int1d_flipy', True): ystride = -1 yslice = slice(None, None, ystride) trimy = int(self.config['general'].get('int1d_trimy', 0)) if trimy > 0: yslice = slice(trimy*ystride, -trimy*ystride, ystride) img = img[yslice, xslice] img_id = self.ad_cam.ArrayCounter_RBV q, xi = self.integrator.integrate1d(img, 2048, unit='q_A^-1', correctSolidAngle=True, polarization_factor=0.999) if init: self.int_panel.plot(q, xi, xlabel=r'$Q (\rm\AA^{-1})$', marker='+', title='Image %d' % img_id) self.int_panel.Raise() self.int_panel.Show() else: self.int_panel.update_line(0, q, xi, draw=True) self.int_panel.set_title('Image %d' % img_id) @EpicsFunction def onSaveImage(self, event=None): "prompts for and save image to file" defdir = os.getcwd() self.fname = "Image_%i.tiff" % self.ad_cam.ArrayCounter_RBV dlg = wx.FileDialog(None, message='Save Image as', defaultDir=os.getcwd(), defaultFile=self.fname, style=wx.FD_SAVE) path = None if dlg.ShowModal() == wx.ID_OK: path = os.path.abspath(dlg.GetPath()) root, fname = os.path.split(path) epics.caput("%s%sFileName" % self.prefix, self.fsaver, fname) epics.caput("%s%sFileWriteMode" % self.prefix, self.fsaver, 0) time.sleep(0.05) epics.caput("%s%sWriteFile" % self.prefix, self.fsaver, 1) time.sleep(0.05) file_pv = "%s%sFullFileName_RBV" % (self.prefix, self.prefix) print("Saved image File ", epics.caget(file_pv, as_string=True)) def onExit(self, event=None): try: wx.Yield() except: pass self.Destroy() def onAbout(self, event=None): msg = """areaDetector Display version 0.2 Matt Newville <*****@*****.**>""" dlg = wx.MessageDialog(self, msg, "About areaDetector Display", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def buildMenus(self): fmenu = wx.Menu() MenuItem(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage) MenuItem(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard", self.onCopyImage) MenuItem(self, fmenu, "Read Calibration File", "Read PONI Calibration", self.onReadCalibFile) fmenu.AppendSeparator() MenuItem(self, fmenu, "E&xit\tCtrl+Q", "Exit Program", self.onExit) omenu = wx.Menu() MenuItem(self, omenu, "&Rotate CCW\tCtrl+R", "Rotate Counter Clockwise", self.onRot90) MenuItem(self, omenu, "Flip Up/Down\tCtrl+T", "Flip Up/Down", self.onFlipV) MenuItem(self, omenu, "Flip Left/Right\tCtrl+F", "Flip Left/Right", self.onFlipH) MenuItem(self, omenu, "Reset Rotations and Flips", "Reset", self.onResetRotFlips) omenu.AppendSeparator() hmenu = wx.Menu() MenuItem(self, hmenu, "About", "About areaDetector Display", self.onAbout) mbar = wx.MenuBar() mbar.Append(fmenu, "File") mbar.Append(omenu, "Options") mbar.Append(hmenu, "&Help") self.SetMenuBar(mbar) def onResetRotFlips(self, event): self.image.rot90 = 0 self.image.flipv = self.image.fliph = False def onRot90(self, event): self.image.rot90 = (self.image.rot90 - 1) % 4 def onFlipV(self, event): self.image.flipv= not self.image.flipv def onFlipH(self, event): self.image.fliph = not self.image.fliph def set_contrast_level(self, contrast_level=0): self.image.contrast_levels = [contrast_level, 100.0-contrast_level] self.image.Refresh() def write(self, s, panel=0): """write a message to the Status Bar""" self.SetStatusText(text=s, number=panel) @EpicsFunction def onButton(self, event=None, key='free'): key = key.lower() if key.startswith('free'): ftime = self.config['general']['free_run_time'] self.image.restart_fps_counter() self.ad_cam.AcquireTime = ftime self.ad_cam.AcquirePeriod = ftime self.ad_cam.NumImages = int((3*86400.)/ftime) self.ad_cam.Acquire = 1 elif key.startswith('start'): self.image.restart_fps_counter() self.ad_cam.Acquire = 1 elif key.startswith('stop'): self.ad_cam.Acquire = 0 @EpicsFunction def connect_pvs(self, verbose=True): if self.prefix is None or len(self.prefix) < 2: return self.write('Connecting to areaDetector %s' % self.prefix) self.ad_img = epics.Device(self.prefix + 'image1:', delim='', attrs=self.img_attrs) self.ad_cam = epics.Device(self.prefix + 'cam1:', delim='', attrs=self.cam_attrs) if self.config['general']['use_filesaver']: epics.caput("%s%sEnableCallbacks" % (self.prefix, self.fsaver), 1) epics.caput("%s%sAutoSave" % (self.prefix, self.fsaver), 0) epics.caput("%s%sAutoIncrement" % (self.prefix, self.fsaver), 0) epics.caput("%s%sFileWriteMode" % (self.prefix, self.fsaver), 0) time.sleep(0.002) if not self.ad_img.PV('UniqueId_RBV').connected: epics.poll() if not self.ad_img.PV('UniqueId_RBV').connected: self.write('Warning: detector seems to not be connected!') return if verbose: self.write('Connected to detector %s' % self.prefix) self.SetTitle("Epics areaDetector Display: %s" % self.prefix) sizex = self.ad_cam.MaxSizeX_RBV sizey = self.ad_cam.MaxSizeY_RBV sizelabel = 'Image Size: %i x %i pixels' try: sizelabel = sizelabel % (sizex, sizey) except: sizelabel = sizelabel % (0, 0) self.imagesize.SetLabel(sizelabel) self.ad_cam.add_callback('DetectorState_RBV', self.onDetState) self.contrast.set_level_str('0.01') @DelayedEpicsCallback def onDetState(self, pvname=None, value=None, char_value=None, **kw): self.write(char_value, panel=0)
def onProfile(self, x0, y0, x1, y1): width = self.ad_cam.SizeX height = self.ad_cam.SizeY x0, y0 = int(x0 * width), int(y0 * height) x1, y1 = int(x1 * width), int(y1 * height) dx, dy = abs(x1 - x0), abs(y1 - y0) if dx < 2 and dy < 2: return outdat = [] if self.colormode == 2: self.data.shape = (self.im_size[1], self.im_size[0], 3) else: self.data.shape = self.im_size[1], self.im_size[0] if dy > dx: _y0 = min(int(y0), int(y1+0.5)) _y1 = max(int(y0), int(y1+0.5)) for iy in range(_y0, _y1): ix = int(x0 + (iy-int(y0))*(x1-x0)/(y1-y0)) outdat.append((ix, iy)) else: _x0 = min(int(x0), int(x1+0.5)) _x1 = max(int(x0), int(x1+0.5)) for ix in range(_x0, _x1): iy = int(y0 + (ix-int(x0))*(y1-y0)/(x1-x0)) outdat.append((ix, iy)) if self.lineplotter is None: self.lineplotter = PlotFrame(self, title='Image Profile') else: try: self.lineplotter.Raise() except PyDeadObjectError: self.lineplotter = PlotFrame(self, title='Image Profile') if self.colormode == 2: x, y, r, g, b = [], [], [], [], [] for ix, iy in outdat: x.append(ix) y.append(iy) r.append(self.data[iy,ix,0]) g.append(self.data[iy,ix,1]) b.append(self.data[iy,ix,2]) xlabel = 'Pixel (x)' if dy > dx: x = y xlabel = 'Pixel (y)' self.lineplotter.plot(x, r, color='red', label='red', xlabel=xlabel, ylabel='Intensity', title='Image %i' % self.ad_cam.ArrayCounter_RBV) self.lineplotter.oplot(x, g, color='green', label='green') self.lineplotter.oplot(x, b, color='blue', label='blue') else: x, y, z = [], [], [] for ix, iy in outdat: x.append(ix) y.append(iy) z.append(self.data[iy,ix]) xlabel = 'Pixel (x)' if dy > dx: x = y xlabel = 'Pixel (y)' self.lineplotter.plot(x, z, color='k', xlabel=xlabel, ylabel='Intensity', title='Image %i' % self.ad_cam.ArrayCounter_RBV) self.lineplotter.Show() self.lineplotter.Raise()
class AD_Display(wx.Frame): """AreaDetector Display """ img_attrs = ('ArrayData', 'UniqueId_RBV', 'NDimensions_RBV', 'ArraySize0_RBV', 'ArraySize1_RBV', 'ArraySize2_RBV', 'ColorMode_RBV') cam_attrs = ('Acquire', 'ArrayCounter', 'ArrayCounter_RBV', 'DetectorState_RBV', 'NumImages', 'ColorMode', 'DataType_RBV', 'Gain', 'AcquireTime', 'AcquirePeriod', 'ImageMode', 'MaxSizeX_RBV', 'MaxSizeY_RBV', 'TriggerMode', 'SizeX', 'SizeY', 'MinX', 'MinY') # plugins to enable enabled_plugins = ('image1', 'Over1', 'ROI1', 'JPEG1', 'TIFF1') stat_msg = 'Read %.1f%% of images: rate=%.1f frames/sec' def __init__(self, prefix=None, app=None, scale=1.0, approx_height=1200, known_cameras=None): self.app = app self.ad_img = None self.ad_cam = None self.imgcount = 0 self.prefix = prefix self.fname = 'AD_Image.tiff' self.scale = scale self.known_cameras = known_cameras self.arrsize = [0,0,0] self.imbuff = None self.d_size = None self.im_size = None self.colormode = 0 self.last_update = 0.0 self.n_img = 0 self.imgcount_start = 0 self.n_drawn = 0 self.img_id = 0 self.starttime = time.time() self.drawing = False self.lineplotter = None self.zoom_lims = [] wx.Frame.__init__(self, None, -1, "Epics Area Detector Display", style=wx.DEFAULT_FRAME_STYLE) if known_cameras is not None: self.ConnectToCamera(name=self.prefix) else: self.ConnectToPV(name=self.prefix) self.img_w = 0 self.img_h = 0 self.wximage = wx.EmptyImage(1024, 1360) # 1360, 1024) # approx_height, 1.5*approx_height) self.buildMenus() self.buildFrame() def OnLeftUp(self, event): if self.image is not None: self.image.OnLeftUp(event) def ConnectToCamera(self, name=None, event=None): if name is None: name = '' if self.known_cameras is None: return cam_names = self.known_cameras.keys() cam_names.sort() dlg = wx.SingleChoiceDialog(self, 'Select Camera', caption='Select Camera', choices=cam_names) dlg.Raise() if dlg.ShowModal() == wx.ID_OK: cname = dlg.GetStringSelection() if cname in self.known_cameras: self.prefix = self.known_cameras[cname] wx.CallAfter(self.connect_pvs) dlg.Destroy() def ConnectToPV(self, event=None, name=None): print 'Connect To PV ', name , event if name is None: name = '' dlg = wx.TextEntryDialog(self, 'Enter PV for Area Detector', caption='Enter PV for Area Detector', defaultValue=name) dlg.Raise() if dlg.ShowModal() == wx.ID_OK: self.prefix = dlg.GetValue() wx.CallAfter(self.connect_pvs) dlg.Destroy() def onCopyImage(self, event=None): "copy bitmap of canvas to system clipboard" bmp = wx.BitmapDataObject() bmp.SetBitmap(wx.BitmapFromImage(self.wximage)) wx.TheClipboard.Open() wx.TheClipboard.SetData(bmp) wx.TheClipboard.Close() wx.TheClipboard.Flush() @EpicsFunction def CameraOff(self): try: self.ad_cam.Acquire = 0 except: pass @EpicsFunction def onSaveImage(self, event=None): "prompts for and save image to file" defdir = os.getcwd() self.fname = "Image_%i.tiff" % self.ad_cam.ArrayCounter_RBV dlg = wx.FileDialog(None, message='Save Image as', defaultDir=os.getcwd(), defaultFile=self.fname, style=wx.SAVE) path = None if dlg.ShowModal() == wx.ID_OK: path = os.path.abspath(dlg.GetPath()) dlg.Destroy() if path is not None and self.data is not None: Image.frombuffer(self.im_mode, self.im_size, self.data.flatten(), 'raw', self.im_mode, 0, 1).save(path) def onExit(self, event=None): try: wx.Yield() except: pass self.CameraOff() self.Destroy() def onAbout(self, event=None): msg = """Epics Image Display version 0.2 http://pyepics.github.com/epicsapps/ Matt Newville <*****@*****.**>""" dlg = wx.MessageDialog(self, msg, "About Epics Image Display", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def buildMenus(self): fmenu = wx.Menu() add_menu(self, fmenu, "&Connect to Pre-defiend Camera", "Connect to PV", self.ConnectToCamera) add_menu(self, fmenu, "&Connect to AreaDetector PV\tCtrl+O", "Connect to PV", self.ConnectToPV) add_menu(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage) add_menu(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard", self.onCopyImage) fmenu.AppendSeparator() add_menu(self, fmenu, "E&xit\tCtrl+Q", "Exit Program", self.onExit) omenu = wx.Menu() add_menu(self, omenu, "&Zoom out\tCtrl+Z", "Zoom Out", self.unZoom) add_menu(self, omenu, "Reset Image Counter", "Set Image Counter to 0", self.onResetImageCounter) omenu.AppendSeparator() add_menu(self, omenu, "&Rotate Clockwise\tCtrl+R", "Rotate Clockwise", self.onRotCW) add_menu(self, omenu, "Rotate CounterClockwise", "Rotate Counter Clockwise", self.onRotCCW) add_menu(self, omenu, "Flip Up/Down\tCtrl+T", "Flip Up/Down", self.onFlipV) add_menu(self, omenu, "Flip Left/Right\tCtrl+F", "Flip Left/Right", self.onFlipH) omenu.AppendSeparator() self.CM_ZOOM = wx.NewId() self.CM_SHOW = wx.NewId() self.CM_PROF = wx.NewId() omenu.Append(self.CM_ZOOM, "Cursor Mode: Zoom to Box\tCtrl+B" , "Zoom to box by clicking and dragging", wx.ITEM_RADIO) omenu.Append(self.CM_SHOW, "Cursor Mode: Show X,Y\tCtrl+X", "Show X,Y, Intensity Values", wx.ITEM_RADIO) omenu.Append(self.CM_PROF, "Cursor Mode: Line Profile\tCtrl+L", "Show Line Profile", wx.ITEM_RADIO) self.Bind(wx.EVT_MENU, self.onCursorMode, id=self.CM_ZOOM) self.Bind(wx.EVT_MENU, self.onCursorMode, id=self.CM_PROF) self.Bind(wx.EVT_MENU, self.onCursorMode, id=self.CM_SHOW) hmenu = wx.Menu() add_menu(self, hmenu, "About", "About Epics AreadDetector Display", self.onAbout) mbar = wx.MenuBar() mbar.Append(fmenu, "File") mbar.Append(omenu, "Options") mbar.Append(hmenu, "&Help") self.SetMenuBar(mbar) def onCursorMode(self, event=None): if event.Id == self.CM_ZOOM: self.image.cursor_mode = 'zoom' elif event.Id == self.CM_PROF: self.image.cursor_mode = 'profile' elif event.Id == self.CM_SHOW: self.image.cursor_mode = 'show' @DelayedEpicsCallback def onResetImageCounter(self, event=None): self.ad_cam.ArrayCounter = 0 def onRotCW(self, event): self.image.rot90 = (self.image.rot90 + 1) % 4 self.image.Refresh() def onRotCCW(self, event): self.image.rot90 = (self.image.rot90 - 1) % 4 self.image.Refresh() def onFlipV(self, event): self.image.flipv= not self.image.flipv self.image.Refresh() def onFlipH(self, event): self.image.fliph = not self.image.fliph self.image.Refresh() def buildFrame(self): sbar = self.CreateStatusBar(3, wx.CAPTION|wx.THICK_FRAME) sfont = sbar.GetFont() sfont.SetWeight(wx.BOLD) sfont.SetPointSize(10) sbar.SetFont(sfont) self.SetStatusWidths([-3, -1, -1]) self.SetStatusText('',0) sizer = wx.GridBagSizer(10, 4) panel = wx.Panel(self) self.panel = panel labstyle = wx.ALIGN_LEFT|wx.ALIGN_BOTTOM|wx.EXPAND ctrlstyle = wx.ALIGN_LEFT|wx.ALIGN_BOTTOM rlabstyle = wx.ALIGN_RIGHT|wx.RIGHT|wx.TOP|wx.EXPAND txtstyle=wx.ALIGN_LEFT|wx.ST_NO_AUTORESIZE|wx.TE_PROCESS_ENTER self.wids = {} self.wids['exptime'] = PVFloatCtrl(panel, pv=None, size=(100, -1)) self.wids['period'] = PVFloatCtrl(panel, pv=None, size=(100, -1)) self.wids['numimages'] = PVFloatCtrl(panel, pv=None, size=(100, -1)) self.wids['gain'] = PVFloatCtrl(panel, pv=None, size=(100, -1), minval=0, maxval=20) self.wids['imagemode'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['triggermode'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['color'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['start'] = wx.Button(panel, -1, label='Start', size=(50, -1)) self.wids['stop'] = wx.Button(panel, -1, label='Stop', size=(50, -1)) if HAS_OVERLAY_DEVICE: self.wids['o1color'] = csel.ColourSelect(panel, -1, "", '#FEFEFE', size=(60, 25)) self.wids['o1color'].Bind(csel.EVT_COLOURSELECT, Closure(self.onColor, item=1)) self.wids['o1posx'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o1posy'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o1sizx'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o1sizy'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o1shape'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['o1use'] = PVEnumChoice(panel, pv=None, size=(50, -1)) self.wids['o1name'] = PVTextCtrl(panel, pv=None, size=(100, -1)) self.wids['o2color'] = csel.ColourSelect(panel, -1, "", '#FEFEFE', size=(60, 25)) self.wids['o2color'].Bind(csel.EVT_COLOURSELECT, Closure(self.onColor, item=2)) self.wids['o2posx'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o2posy'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o2sizx'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o2sizy'] = PVFloatCtrl(panel, pv=None, size=(50, -1), minval=0) self.wids['o2shape'] = PVEnumChoice(panel, pv=None, size=(100, -1)) self.wids['o2use'] = PVEnumChoice(panel, pv=None, size=(50, -1)) self.wids['o2name'] = PVTextCtrl(panel, pv=None, size=(100, -1)) for key in ('start', 'stop'): self.wids[key].Bind(wx.EVT_BUTTON, Closure(self.onEntry, key=key)) self.wids['zoomsize']= wx.StaticText(panel, -1, size=(250,-1), style=txtstyle) self.wids['fullsize']= wx.StaticText(panel, -1, size=(250,-1), style=txtstyle) def txt(label, size=100): return wx.StaticText(panel, label=label, size=(size, -1), style=labstyle) def lin(len=30, wid=2, style=wx.LI_HORIZONTAL): return wx.StaticLine(panel, size=(len, wid), style=style) sizer.Add(txt(' '), (0, 0), (1, 1), labstyle) sizer.Add(txt('Image Mode '), (1, 0), (1, 1), labstyle) sizer.Add(self.wids['imagemode'], (1, 1), (1, 2), ctrlstyle) sizer.Add(txt('# Images '), (2, 0), (1, 1), labstyle) sizer.Add(self.wids['numimages'], (2, 1), (1, 2), ctrlstyle) sizer.Add(txt('Trigger Mode '), (3, 0), (1, 1), labstyle) sizer.Add(self.wids['triggermode'], (3, 1), (1, 2), ctrlstyle) sizer.Add(txt('Period '), (4, 0), (1, 1), labstyle) sizer.Add(self.wids['period'], (4, 1), (1, 2), ctrlstyle) sizer.Add(txt('Exposure Time '), (5, 0), (1, 1), labstyle) sizer.Add(self.wids['exptime'], (5, 1), (1, 2), ctrlstyle) sizer.Add(txt('Gain '), (6, 0), (1, 1), labstyle) sizer.Add(self.wids['gain'], (6, 1), (1, 2), ctrlstyle) sizer.Add(txt('Color Mode'), (7, 0), (1, 1), labstyle) sizer.Add(self.wids['color'], (7, 1), (1, 2), ctrlstyle) sizer.Add(txt('Acquire '), (9, 0), (1, 1), labstyle) sizer.Add(self.wids['start'], (9, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['stop'], (9, 2), (1, 1), ctrlstyle) sizer.Add(self.wids['fullsize'], (12, 0), (1, 3), labstyle) sizer.Add(self.wids['zoomsize'], (13, 0), (1, 3), labstyle) sizer.Add(lin(75), (15, 0), (1, 3), labstyle) if HAS_OVERLAY_DEVICE: ir = 16 sizer.Add(txt('Overlay 1:'), (ir+0, 0), (1, 1), labstyle) sizer.Add(self.wids['o1use'], (ir+0, 1), (1, 2), ctrlstyle) sizer.Add(txt('Shape:'), (ir+1, 0), (1, 1), labstyle) sizer.Add(self.wids['o1shape'], (ir+1, 1), (1, 2), ctrlstyle) sizer.Add(txt('Name:'), (ir+2, 0), (1, 1), labstyle) sizer.Add(self.wids['o1name'], (ir+2, 1), (1, 2), ctrlstyle) sizer.Add(txt('Position '), (ir+3, 0), (1, 1), labstyle) sizer.Add(self.wids['o1posx'], (ir+3, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['o1posy'], (ir+3, 2), (1, 1), ctrlstyle) sizer.Add(txt('Size '), (ir+4, 0), (1, 1), labstyle) sizer.Add(self.wids['o1sizx'], (ir+4, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['o1sizy'], (ir+4, 2), (1, 1), ctrlstyle) sizer.Add(txt('Color '), (ir+5, 0), (1, 1), labstyle) sizer.Add(self.wids['o1color'], (ir+5, 1), (1, 2), ctrlstyle) sizer.Add(lin(75), (ir+6, 0), (1, 3), labstyle) ir = ir + 7 sizer.Add(txt('Overlay 1:'), (ir+0, 0), (1, 1), labstyle) sizer.Add(self.wids['o2use'], (ir+0, 1), (1, 2), ctrlstyle) sizer.Add(txt('Shape:'), (ir+1, 0), (1, 1), labstyle) sizer.Add(self.wids['o2shape'], (ir+1, 1), (1, 2), ctrlstyle) sizer.Add(txt('Name:'), (ir+2, 0), (1, 1), labstyle) sizer.Add(self.wids['o2name'], (ir+2, 1), (1, 2), ctrlstyle) sizer.Add(txt('Position '), (ir+3, 0), (1, 1), labstyle) sizer.Add(self.wids['o2posx'], (ir+3, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['o2posy'], (ir+3, 2), (1, 1), ctrlstyle) sizer.Add(txt('Size '), (ir+4, 0), (1, 1), labstyle) sizer.Add(self.wids['o2sizx'], (ir+4, 1), (1, 1), ctrlstyle) sizer.Add(self.wids['o2sizy'], (ir+4, 2), (1, 1), ctrlstyle) sizer.Add(txt('Color '), (ir+5, 0), (1, 1), labstyle) sizer.Add(self.wids['o2color'], (ir+5, 1), (1, 2), ctrlstyle) sizer.Add(lin(75), (ir+6, 0), (1, 3), labstyle) self.image = ImageView(self, size=(1360, 1024), onzoom=self.onZoom, onprofile=self.onProfile, onshow=self.onShowXY) panel.SetSizer(sizer) sizer.Fit(panel) mainsizer = wx.BoxSizer(wx.HORIZONTAL) mainsizer.Add(panel, 0, wx.LEFT|wx.GROW|wx.ALL, 5) mainsizer.Add(self.image, 1, wx.CENTER|wx.GROW|wx.ALL, 5) self.SetSizer(mainsizer) mainsizer.Fit(self) self.SetAutoLayout(True) try: self.SetIcon(wx.Icon(ICON_FILE, wx.BITMAP_TYPE_ICO)) except: pass self.RefreshImage() wx.CallAfter(self.connect_pvs ) def messag(self, s, panel=0): """write a message to the Status Bar""" wx.CallAfter(Closure(self.SetStatusText, text=s, number=panel)) # self.SetStatusText(s, panel) @EpicsFunction def unZoom(self, event=None, full=False): if self.zoom_lims is None or full: self.zoom_lims = [] if len(self.zoom_lims) == 0: xmin, ymin = 0, 0 width = self.ad_cam.MaxSizeX_RBV height = self.ad_cam.MaxSizeY_RBV self.zoom_lims = [] else: xmin, ymin, width, height = self.zoom_lims.pop() if (self.ad_cam.MinX == xmin and self.ad_cam.MinY == ymin and self.ad_cam.SizeX == width and self.ad_cam.SizeY == height): try: xmin, ymin, width, height = self.zoom_lims.pop() except: xmin, ymin = 0, 0 width = self.ad_cam.MaxSizeX_RBV height = self.ad_cam.MaxSizeY_RBV self.ad_cam.MinX = xmin self.ad_cam.MinY = ymin self.ad_cam.SizeX = width self.ad_cam.SizeY = height self.zoom_lims.append((xmin, ymin, width, height)) time.sleep(0.05) self.showZoomsize() if self.ad_cam.Acquire == 0 and self.im_size is not None: self.img_w = width self.img_h = height try: if self.colormode == 2: self.data.shape = [self.im_size[1], self.im_size[0], 3] zdata = self.data[ymin:ymin+height, xmin:xmin+width,:] else: self.data.shape = self.im_size[1], self.im_size[0] zdata = self.data[ymin:ymin+height,xmin:xmin+width] except ValueError: pass self.data = zdata #self.data.flatten() self.im_size = (width, height) # print zdata.shape, width, height, self.im_mode self.DatatoImage() # zdata, (width, height), self.im_mode) self.RefreshImage() self.image.Refresh() @EpicsFunction def onColor(self, event=None, item=None): if HAS_OVERLAY_DEVICE: color = event.GetValue() over = self.ad_overlays[item-1] over.Red = color[0] over.Green = color[1] over.Blue = color[2] @EpicsFunction def showZoomsize(self): try: msg = 'Showing: %i x %i pixels' % (self.ad_cam.SizeX, self.ad_cam.SizeY) self.wids['zoomsize'].SetLabel(msg) except: pass @EpicsFunction def onZoom(self, x0, y0, x1, y1): width = self.ad_cam.SizeX height = self.ad_cam.SizeY xmin = max(0, int(self.ad_cam.MinX + x0 * width)) ymin = max(0, int(self.ad_cam.MinY + y0 * height)) width = int(x1 * width) height = int(y1 * height) if width < 2 or height < 2: return self.ad_cam.MinX = xmin self.ad_cam.MinY = ymin self.ad_cam.SizeX = width self.ad_cam.SizeY = height if self.zoom_lims is None: self.zoom_lims = [] self.zoom_lims.append((xmin, ymin, width, height)) time.sleep(0.05) self.showZoomsize() if self.ad_cam.Acquire == 0: self.img_w = width self.img_h = height if self.colormode == 2: self.data.shape = [self.im_size[1], self.im_size[0], 3] zdata = self.data[ymin:ymin+height, xmin:xmin+width,:] else: self.data.shape = self.im_size[1], self.im_size[0] zdata = self.data[ymin:ymin+height,xmin:xmin+width] self.data = zdata #. flatten() self.im_size = (width, height) self.DatatoImage() self.image.Refresh() def DatatoImage(self): #, data, size, mode): """convert raw data to image""" #x = debugtime() width, height = self.im_size d_size = (int(width*self.scale), int(height*self.scale)) data = self.data.flatten() #x.add('flatten') if self.imbuff is None or d_size != self.d_size or self.im_mode == 'L': try: self.imbuff = Image.frombuffer(self.im_mode, self.im_size, data, 'raw', self.im_mode, 0, 1) #x.add('made image') except: return self.d_size = d_size = (int(width*self.scale), int(height*self.scale)) if self.imbuff.size != d_size: self.imbuff = self.imbuff.resize(d_size) #x.add('resized imbuff') if self.wximage.GetSize() != self.imbuff.size: self.wximage = wx.EmptyImage(d_size[0], d_size[1]) #x.add('created wximage %s ' % (repr(self.wximage.GetSize()))) if self.im_mode == 'L': self.wximage.SetData(self.imbuff.convert('RGB').tostring()) elif self.im_mode == 'RGB': data.shape = (3, width, height) self.wximage = wx.ImageFromData(width, height, data) #x.add('set wx image wximage : %i, %i ' % d_size) self.image.SetValue(self.wximage) #x.add('set image value') #x.show() def onProfile(self, x0, y0, x1, y1): width = self.ad_cam.SizeX height = self.ad_cam.SizeY x0, y0 = int(x0 * width), int(y0 * height) x1, y1 = int(x1 * width), int(y1 * height) dx, dy = abs(x1 - x0), abs(y1 - y0) if dx < 2 and dy < 2: return outdat = [] if self.colormode == 2: self.data.shape = (self.im_size[1], self.im_size[0], 3) else: self.data.shape = self.im_size[1], self.im_size[0] if dy > dx: _y0 = min(int(y0), int(y1+0.5)) _y1 = max(int(y0), int(y1+0.5)) for iy in range(_y0, _y1): ix = int(x0 + (iy-int(y0))*(x1-x0)/(y1-y0)) outdat.append((ix, iy)) else: _x0 = min(int(x0), int(x1+0.5)) _x1 = max(int(x0), int(x1+0.5)) for ix in range(_x0, _x1): iy = int(y0 + (ix-int(x0))*(y1-y0)/(x1-x0)) outdat.append((ix, iy)) if self.lineplotter is None: self.lineplotter = PlotFrame(self, title='Image Profile') else: try: self.lineplotter.Raise() except PyDeadObjectError: self.lineplotter = PlotFrame(self, title='Image Profile') if self.colormode == 2: x, y, r, g, b = [], [], [], [], [] for ix, iy in outdat: x.append(ix) y.append(iy) r.append(self.data[iy,ix,0]) g.append(self.data[iy,ix,1]) b.append(self.data[iy,ix,2]) xlabel = 'Pixel (x)' if dy > dx: x = y xlabel = 'Pixel (y)' self.lineplotter.plot(x, r, color='red', label='red', xlabel=xlabel, ylabel='Intensity', title='Image %i' % self.ad_cam.ArrayCounter_RBV) self.lineplotter.oplot(x, g, color='green', label='green') self.lineplotter.oplot(x, b, color='blue', label='blue') else: x, y, z = [], [], [] for ix, iy in outdat: x.append(ix) y.append(iy) z.append(self.data[iy,ix]) xlabel = 'Pixel (x)' if dy > dx: x = y xlabel = 'Pixel (y)' self.lineplotter.plot(x, z, color='k', xlabel=xlabel, ylabel='Intensity', title='Image %i' % self.ad_cam.ArrayCounter_RBV) self.lineplotter.Show() self.lineplotter.Raise() def onShowXY(self, xval, yval): ix = max(0, int( xval * self.ad_cam.SizeX)) iy = max(0, int( yval * self.ad_cam.SizeY)) if self.colormode == 2: self.data.shape = (self.im_size[1], self.im_size[0], 3) ival = tuple(self.data[iy, ix, :]) smsg = 'Pixel %i, %i, (R, G, B) = %s' % (ix, iy, repr(ival)) else: self.data.shape = self.im_size[1], self.im_size[0] ival = self.data[iy, ix] smsg = 'Pixel %i, %i, Intensity = %i' % (ix, iy, ival) self.messag(smsg, panel=1) def onName(self, evt=None, **kws): if evt is None: return s = evt.GetString() s = str(s).strip() if s.endswith(':image1:'): s = s[:-8] if s.endswith(':cam1:'): s = s[:-6] if s.endswith(':'): s = s[:-1] self.prefix = s self.connect_pvs() @EpicsFunction def onEntry(self, evt=None, key='name', **kw): if evt is None: return if key == 'start': self.n_img = 0 self.n_drawn = 0 self.starttime = time.time() self.imgcount_start = self.ad_cam.ArrayCounter_RBV self.ad_cam.Acquire = 1 elif key == 'stop': self.ad_cam.Acquire = 0 elif key == 'unzoom': self.unZoom() else: print 'unknown Entry ? ', key @EpicsFunction def connect_pvs(self, verbose=True): if self.prefix is None or len(self.prefix) < 2: return try: self.ad_cam.Acquire = 0 except: pass if self.prefix.endswith(':'): self.prefix = self.prefix[:-1] if self.prefix.endswith(':image1'): self.prefix = self.prefix[:-7] if self.prefix.endswith(':cam1'): self.prefix = self.prefix[:-5] if verbose: self.messag('Connecting to AD %s' % self.prefix) self.ad_img = epics.Device(self.prefix + ':image1:', delim='', attrs=self.img_attrs) self.ad_cam = epics.Device(self.prefix + ':cam1:', delim='', attrs=self.cam_attrs) self.ad_overlays = [] if HAS_OVERLAY_DEVICE: for ix in (1, 2): pvn ='%s:Over1:%i:' % (self.prefix, ix) self.ad_overlays.append(AD_OverlayPlugin(pvn)) time.sleep(0.010) if not self.ad_img.PV('UniqueId_RBV').connected: epics.poll() if not self.ad_img.PV('UniqueId_RBV').connected: self.messag('Warning: Camera seems to not be connected!') return if verbose: self.messag('Connected to AD %s' % self.prefix) self.SetTitle("Epics Image Display: %s" % self.prefix) self.wids['color'].SetPV(self.ad_cam.PV('ColorMode')) self.wids['exptime'].SetPV(self.ad_cam.PV('AcquireTime')) self.wids['period'].SetPV(self.ad_cam.PV('AcquirePeriod')) self.wids['gain'].SetPV(self.ad_cam.PV('Gain')) self.wids['numimages'].SetPV(self.ad_cam.PV('NumImages')) self.wids['imagemode'].SetPV(self.ad_cam.PV('ImageMode')) self.wids['triggermode'].SetPV(self.ad_cam.PV('TriggerMode')) sizex = self.ad_cam.MaxSizeX_RBV sizey = self.ad_cam.MaxSizeY_RBV if HAS_OVERLAY_DEVICE: over = self.ad_overlays[0] c1 = (over.Red, over.Green, over.Blue) self.wids['o1color'].SetColour(hexcolor(c1)) self.wids['o1posx'].SetPV(over.PV('PositionX')) self.wids['o1posx'].SetMax(sizex) self.wids['o1posy'].SetPV(over.PV('PositionY')) self.wids['o1posy'].SetMax(sizey) self.wids['o1sizx'].SetPV(over.PV('SizeX')) self.wids['o1sizx'].SetMax(sizex) self.wids['o1sizy'].SetPV(over.PV('SizeY')) self.wids['o1sizy'].SetMax(sizey) self.wids['o1shape'].SetPV(over.PV('Shape')) self.wids['o1name'].SetPV(over.PV('Name')) self.wids['o1use'].SetPV(over.PV('Use')) over = self.ad_overlays[1] c1 = (over.Red, over.Green, over.Blue) self.wids['o2color'].SetColour(hexcolor(c1)) self.wids['o2posx'].SetPV(over.PV('PositionX')) self.wids['o2posx'].SetMax(sizex) self.wids['o2posy'].SetPV(over.PV('PositionY')) self.wids['o2posy'].SetMax(sizey) self.wids['o2sizx'].SetPV(over.PV('SizeX')) self.wids['o2sizx'].SetMax(sizex) self.wids['o2sizy'].SetPV(over.PV('SizeY')) self.wids['o2sizy'].SetMax(sizey) self.wids['o2shape'].SetPV(over.PV('Shape')) self.wids['o2name'].SetPV(over.PV('Name')) self.wids['o2use'].SetPV(over.PV('Use')) sizelabel = 'Image Size: %i x %i pixels' try: sizelabel = sizelabel % (sizex, sizey) except: sizelabel = sizelabel % (0, 0) self.wids['fullsize'].SetLabel(sizelabel) self.showZoomsize() self.ad_img.add_callback('ArrayCounter_RBV', self.onNewImage) self.ad_img.add_callback('ArraySize0_RBV', self.onProperty, dim=0) self.ad_img.add_callback('ArraySize1_RBV', self.onProperty, dim=1) self.ad_img.add_callback('ArraySize2_RBV', self.onProperty, dim=2) self.ad_img.add_callback('ColorMode_RBV', self.onProperty, dim='color') self.ad_cam.add_callback('DetectorState_RBV', self.onDetState) epics.caput("%s:cam1:ArrayCallbacks" % self.prefix, 1) for p in self.enabled_plugins: epics.caput("%s:%s:EnableCallbacks" % (self.prefix, p), 1) epics.caput("%s:JPEG1:NDArrayPort" % self.prefix, "OVER1") epics.caput("%s:TIFF1:NDArrayPort" % self.prefix, "OVER1") epics.caput("%s:image1:NDArrayPort"% self.prefix, "OVER1") self.ad_cam.Acquire = 1 self.GetImageSize() self.unZoom() epics.poll() self.RefreshImage() @EpicsFunction def GetImageSize(self): self.arrsize = [1,1,1] self.arrsize[0] = self.ad_img.ArraySize0_RBV self.arrsize[1] = self.ad_img.ArraySize1_RBV self.arrsize[2] = self.ad_img.ArraySize2_RBV self.colormode = self.ad_img.ColorMode_RBV self.img_w = self.arrsize[1] self.img_h = self.arrsize[0] if self.colormode == 2: self.img_w = self.arrsize[2] self.img_h = self.arrsize[1] @DelayedEpicsCallback def onDetState(self, pvname=None, value=None, char_value=None, **kw): self.messag(char_value, panel=1) @DelayedEpicsCallback def onProperty(self, pvname=None, value=None, dim=None, **kw): if dim=='color': self.colormode=value else: self.arrsize[dim] = value @DelayedEpicsCallback def onNewImage(self, pvname=None, value=None, **kw): if value != self.img_id: self.img_id = value if not self.drawing: self.drawing = True self.RefreshImage() @EpicsFunction def RefreshImage(self, pvname=None, **kws): try: wx.Yield() except: pass d = debugtime() if self.ad_img is None or self.ad_cam is None: return imgdim = self.ad_img.NDimensions_RBV imgcount = self.ad_cam.ArrayCounter_RBV now = time.time() if (imgcount == self.imgcount or abs(now - self.last_update) < 0.025): self.drawing = False return d.add('refresh img start') self.imgcount = imgcount self.drawing = True self.n_drawn += 1 self.n_img = imgcount - self.imgcount_start #print 'ImgCount, n_drawn: ', imgcount, self.n_img, self.n_drawn self.last_update = time.time() self.image.can_resize = False xmin = self.ad_cam.MinX ymin = self.ad_cam.MinY width = self.ad_cam.SizeX height = self.ad_cam.SizeY arraysize = self.arrsize[0] * self.arrsize[1] if imgdim == 3: arraysize = arraysize * self.arrsize[2] if not self.ad_img.PV('ArrayData').connected: self.drawing = False return d.add('refresh img before raw get %i' % arraysize) rawdata = self.ad_img.PV('ArrayData').get(count=arraysize) d.add('refresh img after raw get') im_mode = 'L' im_size = (self.arrsize[0], self.arrsize[1]) if self.colormode == 2: im_mode = 'RGB' im_size = [self.arrsize[1], self.arrsize[2]] if (self.colormode == 0 and isinstance(rawdata, np.ndarray) and rawdata.dtype != np.uint8): im_mode = 'I' rawdata = rawdata.astype(np.uint32) d.add('refresh img before msg') self.messag(' Image # %i ' % self.ad_cam.ArrayCounter_RBV, panel=2) d.add('refresh img before get image size') self.GetImageSize() self.im_size = im_size self.im_mode = im_mode self.data = rawdata d.add('refresh img before data to image') self.DatatoImage() d.add('refresh img after data to image') self.image.can_resize = True nmissed = max(0, self.n_img-self.n_drawn) delt = time.time()-self.starttime percent_drawn = self.n_drawn * 100 / (self.n_drawn+nmissed) smsg = self.stat_msg % (percent_drawn, self.n_drawn/delt) self.messag(smsg, panel=0) self.drawing = False d.add('refresh img done')
class EigerFrame(wx.Frame): """AreaDetector Display """ img_attrs = ('ArrayData', 'UniqueId_RBV') cam_attrs = ('Acquire', 'DetectorState_RBV', 'ArrayCounter', 'ArrayCounter_RBV', 'ThresholdEnergy', 'ThresholdEnergy_RBV', 'PhotonEnergy', 'PhotonEnergy_RBV', 'NumImages', 'NumImages_RBV', 'AcquireTime', 'AcquireTime_RBV', 'AcquirePeriod', 'AcquirePeriod_RBV', 'TriggerMode', 'TriggerMode_RBV') # plugins to enable enabled_plugins = ('image1', 'Over1', 'ROI1', 'JPEG1', 'TIFF1') def __init__(self, prefix=None, url=None, scale=1.0): self.ad_img = None self.ad_cam = None if prefix is None: dlg = SavedParameterDialog(label='Detector Prefix', title='Connect to Eiger Detector', configfile='.ad_eigerdisplay.dat') res = dlg.GetResponse() dlg.Destroy() if res.ok: prefix = res.value self.prefix = prefix self.fname = 'Eiger.tif' self.esimplon = None if url is not None and HAS_SIMPLON: self.esimplon = EigerSimplon(url, prefix=prefix+'cam1:') self.lineplotter = None self.calib = {} self.integrator = None self.int_panel = None self.int_lastid = None self.contrast_levels = None self.scandb = None wx.Frame.__init__(self, None, -1, "Eiger500K Area Detector Display", style=wx.DEFAULT_FRAME_STYLE) self.buildMenus() self.buildFrame() wx.CallAfter(self.connect_escandb) def connect_escandb(self): if HAS_ESCAN and os.environ.get('ESCAN_CREDENTIALS', None) is not None: self.scandb = ScanDB() calib_loc = self.scandb.get_info('eiger_calibration') cal = self.scandb.get_detectorconfig(calib_loc) self.setup_calibration(json.loads(cal.text)) def buildFrame(self): sbar = self.CreateStatusBar(3, wx.CAPTION) # |wx.THICK_FRAME) self.SetStatusWidths([-1, -1, -1]) sfont = sbar.GetFont() sfont.SetWeight(wx.BOLD) sfont.SetPointSize(10) sbar.SetFont(sfont) self.SetStatusText('',0) sizer = wx.GridBagSizer(3, 3) panel = self.panel = wx.Panel(self) pvpanel = PVConfigPanel(panel, self.prefix, display_pvs) wsize = (100, -1) lsize = (250, -1) start_btn = wx.Button(panel, label='Start', size=wsize) stop_btn = wx.Button(panel, label='Stop', size=wsize) free_btn = wx.Button(panel, label='Free Run', size=wsize) start_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='start')) stop_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='stop')) free_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='free')) self.cmap_choice = wx.Choice(panel, size=(80, -1), choices=colormaps) self.cmap_choice.SetSelection(0) self.cmap_choice.Bind(wx.EVT_CHOICE, self.onColorMap) self.cmap_reverse = wx.CheckBox(panel, label='Reverse', size=(60, -1)) self.cmap_reverse.Bind(wx.EVT_CHECKBOX, self.onColorMap) self.show1d_btn = wx.Button(panel, label='Show 1D Integration', size=(200, -1)) self.show1d_btn.Bind(wx.EVT_BUTTON, self.onShowIntegration) self.show1d_btn.Disable() self.imagesize = wx.StaticText(panel, label='? x ?', size=(250, 30), style=txtstyle) self.contrast = ContrastChoice(panel, callback=self.set_contrast_level) def lin(len=200, wid=2, style=wx.LI_HORIZONTAL): return wx.StaticLine(panel, size=(len, wid), style=style) irow = 0 sizer.Add(pvpanel, (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(start_btn, (irow, 0), (1, 1), labstyle) sizer.Add(stop_btn, (irow, 1), (1, 1), labstyle) sizer.Add(free_btn, (irow, 2), (1, 1), labstyle) irow += 1 sizer.Add(lin(300), (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(self.imagesize, (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(wx.StaticText(panel, label='Color Map: '), (irow, 0), (1, 1), labstyle) sizer.Add(self.cmap_choice, (irow, 1), (1, 1), labstyle) sizer.Add(self.cmap_reverse, (irow, 2), (1, 1), labstyle) irow += 1 sizer.Add(self.contrast.label, (irow, 0), (1, 1), labstyle) sizer.Add(self.contrast.choice, (irow, 1), (1, 1), labstyle) irow += 1 sizer.Add(self.show1d_btn, (irow, 0), (1, 2), labstyle) panel.SetSizer(sizer) sizer.Fit(panel) # image panel self.image = ADMonoImagePanel(self, prefix=self.prefix, rot90=DEFAULT_ROTATION, size=(400, 750), writer=partial(self.write, panel=2)) mainsizer = wx.BoxSizer(wx.HORIZONTAL) mainsizer.Add(panel, 0, wx.LEFT|wx.GROW|wx.ALL) mainsizer.Add(self.image, 1, wx.CENTER|wx.GROW|wx.ALL) self.SetSizer(mainsizer) mainsizer.Fit(self) self.SetAutoLayout(True) try: self.SetIcon(wx.Icon(ICONFILE, wx.BITMAP_TYPE_ICO)) except: pass wx.CallAfter(self.connect_pvs ) def onColorMap(self, event=None): cmap_name = self.cmap_choice.GetStringSelection() if self.cmap_reverse.IsChecked(): cmap_name = cmap_name + '_r' self.image.colormap = getattr(colormap, cmap_name) self.image.Refresh() def onCopyImage(self, event=None): "copy bitmap of canvas to system clipboard" bmp = wx.BitmapDataObject() bmp.SetBitmap(wx.Bitmap(self.image.GrabWxImage())) wx.TheClipboard.Open() wx.TheClipboard.SetData(bmp) wx.TheClipboard.Close() wx.TheClipboard.Flush() def onReadCalibFile(self, event=None): "read calibration file" wcards = "Poni Files(*.poni)|*.poni|All files (*.*)|*.*" dlg = wx.FileDialog(None, message='Read Calibration File', defaultDir=os.getcwd(), wildcard=wcards, style=wx.FD_OPEN) ppath = None if dlg.ShowModal() == wx.ID_OK: ppath = os.path.abspath(dlg.GetPath()) if os.path.exists(ppath): if self.scandb is not None: CalibrationDialog(self, ppath).Show() else: self.setup_calibration(read_poni(ppath)) def setup_calibration(self, calib): """set up calibration from calibration dict""" if self.image.rot90 in (1, 3): calib['rot3'] = np.pi/2.0 self.calib = calib if HAS_PYFAI: self.integrator = AzimuthalIntegrator(**calib) self.show1d_btn.Enable() def onShowIntegration(self, event=None): if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() def onAutoIntegration(self, event=None): if not event.IsChecked(): self.int_timer.Stop() return if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() self.int_timer.Start(500) def show_1dpattern(self, init=False): if self.calib is None or not HAS_PYFAI: return img = self.ad_img.PV('ArrayData').get() h, w = self.image.GetImageSize() img.shape = (w, h) img = img[3:-3, 1:-1][::-1, :] img_id = self.ad_cam.ArrayCounter_RBV q, xi = self.integrator.integrate1d(img, 2048, unit='q_A^-1', correctSolidAngle=True, polarization_factor=0.999) if init: self.int_panel.plot(q, xi, xlabel=r'$Q (\rm\AA^{-1})$', marker='+', title='Image %d' % img_id) self.int_panel.Raise() self.int_panel.Show() else: self.int_panel.update_line(0, q, xi, draw=True) self.int_panel.set_title('Image %d' % img_id) @EpicsFunction def onSaveImage(self, event=None): "prompts for and save image to file" defdir = os.getcwd() self.fname = "Image_%i.tiff" % self.ad_cam.ArrayCounter_RBV dlg = wx.FileDialog(None, message='Save Image as', defaultDir=os.getcwd(), defaultFile=self.fname, style=wx.FD_SAVE) path = None if dlg.ShowModal() == wx.ID_OK: path = os.path.abspath(dlg.GetPath()) root, fname = os.path.split(path) epics.caput("%sTIFF1:FileName" % self.prefix, fname) epics.caput("%sTIFF1:FileWriteMode" % self.prefix, 0) time.sleep(0.05) epics.caput("%sTIFF1:WriteFile" % self.prefix, 1) time.sleep(0.05) print("Saved TIFF File ", epics.caget("%sTIFF1:FullFileName_RBV" % self.prefix, as_string=True)) def onExit(self, event=None): try: wx.Yield() except: pass self.Destroy() def onAbout(self, event=None): msg = """Eiger Image Display version 0.1 Matt Newville <*****@*****.**>""" dlg = wx.MessageDialog(self, msg, "About Epics Image Display", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def buildMenus(self): fmenu = wx.Menu() MenuItem(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage) MenuItem(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard", self.onCopyImage) MenuItem(self, fmenu, "Read Calibration File", "Read PONI Calibration", self.onReadCalibFile) fmenu.AppendSeparator() MenuItem(self, fmenu, "E&xit\tCtrl+Q", "Exit Program", self.onExit) omenu = wx.Menu() MenuItem(self, omenu, "&Rotate CCW\tCtrl+R", "Rotate Counter Clockwise", self.onRot90) MenuItem(self, omenu, "Flip Up/Down\tCtrl+T", "Flip Up/Down", self.onFlipV) MenuItem(self, omenu, "Flip Left/Right\tCtrl+F", "Flip Left/Right", self.onFlipH) MenuItem(self, omenu, "Reset Rotations and Flips", "Reset", self.onResetRotFlips) omenu.AppendSeparator() hmenu = wx.Menu() MenuItem(self, hmenu, "About", "About Epics AreadDetector Display", self.onAbout) mbar = wx.MenuBar() mbar.Append(fmenu, "File") mbar.Append(omenu, "Options") mbar.Append(hmenu, "&Help") self.SetMenuBar(mbar) def onResetRotFlips(self, event): self.image.rot90 = DEFAULT_ROTATION self.image.flipv = self.fliph = False def onRot90(self, event): self.image.rot90 = (self.image.rot90 - 1) % 4 def onFlipV(self, event): self.image.flipv= not self.image.flipv def onFlipH(self, event): self.image.fliph = not self.image.fliph def set_contrast_level(self, contrast_level=0): self.image.contrast_levels = [contrast_level, 100.0-contrast_level] def write(self, s, panel=0): """write a message to the Status Bar""" self.SetStatusText(text=s, number=panel) @EpicsFunction def onButton(self, event=None, key='free'): key = key.lower() if key.startswith('free'): self.image.restart_fps_counter() self.ad_cam.AcquireTime = 0.25 self.ad_cam.AcquirePeriod = 0.25 self.ad_cam.NumImages = 345600 self.ad_cam.Acquire = 1 elif key.startswith('start'): self.image.restart_fps_counter() self.ad_cam.Acquire = 1 elif key.startswith('stop'): self.ad_cam.Acquire = 0 @EpicsFunction def connect_pvs(self, verbose=True): if self.prefix is None or len(self.prefix) < 2: return if self.prefix.endswith(':'): self.prefix = self.prefix[:-1] if self.prefix.endswith(':image1'): self.prefix = self.prefix[:-7] if self.prefix.endswith(':cam1'): self.prefix = self.prefix[:-5] self.write('Connecting to AD %s' % self.prefix) self.ad_img = epics.Device(self.prefix + ':image1:', delim='', attrs=self.img_attrs) self.ad_cam = epics.Device(self.prefix + ':cam1:', delim='', attrs=self.cam_attrs) epics.caput("%s:TIFF1:EnableCallbacks" % self.prefix, 1) epics.caput("%s:TIFF1:AutoSave" % self.prefix, 0) epics.caput("%s:TIFF1:AutoIncrement" % self.prefix, 0) epics.caput("%s:TIFF1:FileWriteMode" % self.prefix, 0) time.sleep(0.002) if not self.ad_img.PV('UniqueId_RBV').connected: epics.poll() if not self.ad_img.PV('UniqueId_RBV').connected: self.write('Warning: Camera seems to not be connected!') return if verbose: self.write('Connected to AD %s' % self.prefix) self.SetTitle("Epics Image Display: %s" % self.prefix) sizex = self.ad_cam.MaxSizeX_RBV sizey = self.ad_cam.MaxSizeY_RBV sizelabel = 'Image Size: %i x %i pixels' try: sizelabel = sizelabel % (sizex, sizey) except: sizelabel = sizelabel % (0, 0) self.imagesize.SetLabel(sizelabel) self.ad_cam.add_callback('DetectorState_RBV', self.onDetState) self.contrast.set_level_str('0.05') @DelayedEpicsCallback def onDetState(self, pvname=None, value=None, char_value=None, **kw): self.write(char_value, panel=1)
class ArlissMonitoringFrame(wx.Frame): title = 'Sensors Monitoring' def __init__(self): wx.Frame.__init__(self, None, -1, self.title, size=(700, 700)) os.system("banner ARLISS") #Partiendo la ventana en 2 paneles, en uno de ellos van los graficos ##en otro los botones y demas self.Maximize() #Funcion para abrir la ventana maximizada self.sp = wx.SplitterWindow(self) self.p1 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER) self.p2 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER) self.sp.SplitVertically(self.p1, self.p2, 250) self.keycode = '' self.Pause = False self.plotframe = None #Se crean los arreglos que van a guardar los datos self.dataAQ = DataAQ() #Clase que genera datos random, para pruebas self.datagen = DataGen() #Arreglo con los datos self.datos = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []] self.datosGPS = [[], []] for line in open('GPS.txt', 'r'): self.datosGPS[0].append(line.split()[0]) self.datosGPS[1].append(line.split()[1]) #Se corren funciones para inicializar y crear paneles y el menu #En el panel es donde esta todo self.create_menu() self.create_status_bar() self.create_main_panel() #se inicializan los timers #Super importantes, cada 100ms ocurre un evento y se corre una funcion #en este caso: self.on_redraw_timer, la cual redibuja los graficos self.redraw_timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer) self.redraw_timer.Start(100) #Texto estatico wx.StaticText(self.p1, -1, "Latitud \t\t\t Longitud", (20, 80)) wx.StaticText(self.p1, -1, "Altura: ", (20, 605)) wx.StaticText(self.p1, -1, "Distancia: ", (20, 620)) wx.StaticText(self.p1, -1, "Estado: ", (20, 635)) wx.StaticText(self.p1, -1, "Moving ", (20, 650)) wx.StaticText(self.p1, -1, "Fix: ", (20, 665)) self.textoAltura = wx.StaticText(self.p1, -1, "0", (100, 605)) self.textoDistancia = wx.StaticText(self.p1, -1, "0", (100, 620)) self.textoEstado = wx.StaticText(self.p1, -1, "0", (100, 635)) self.textoMoviendose = wx.StaticText(self.p1, -1, "0", (100, 650)) self.textoFix = wx.StaticText(self.p1, -1, "0", (100, 665)) #Se crea una ventana para imprimir los datos de latitud y longitud self.logger = wx.TextCtrl(self.p1, 5, "", wx.Point(0, 100), wx.Size(250, 500), wx.TE_MULTILINE | wx.TE_READONLY) #Boton de prueba, cuando se clickea se crea un evento #y se corre una funcion self.pauseButton = wx.Button( self.p1, wx.ID_STOP, pos=(10, 25)) self.pauseButton.Bind(wx.EVT_BUTTON, self.onPause) self.saveButton = wx.Button( self.p1, wx.ID_SAVE, pos=(150, 25)) self.saveButton.Bind(wx.EVT_BUTTON, self.Save) #Funcion que se corre cada vez que se presiona el boton def Save(self, event): self.saveData(self) def onPause(self, event): if not self.Pause: self.Pause = True else: self.Pause = False def ShowPlotFrame(self, do_raise=True, clear=True): "make sure plot frame is enabled, and visible" if self.plotframe is None: self.plotframe = PlotFrame(self) self.has_plot = False try: self.plotframe.Show() except wx.PyDeadObjectError: self.plotframe = PlotFrame(self) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config() #Creando el menu con todos las diferentes pesta;as y accesos def create_menu(self): self.menubar = wx.MenuBar() menu_file = wx.Menu() m_expt = menu_file.Append( -1, "&Save plot\tCtrl-S", "Save plot to file") self.Bind(wx.EVT_MENU, self.on_save_plot, m_expt) menu_file.AppendSeparator() m_exit = menu_file.Append(-1, "E&xit\tCtrl-X", "Exit") self.Bind(wx.EVT_MENU, self.on_exit, m_exit) self.menubar.Append(menu_file, "&File") saveMenu = wx.Menu() m_Compass = saveMenu.Append(-1, "Plot Compass", "Plotear y guardar los datos de la brujula") self.Bind(wx.EVT_MENU, self.wxmPlotBrujula, m_Compass) m_CompassGoal = saveMenu.Append(-1, "Plot CompassGoal", "Plotear y guardar los datos del angulo con respecto a la meta") self.Bind(wx.EVT_MENU, self.wxmPlotBrujulaGoal, m_CompassGoal) m_PWM1 = saveMenu.Append(-1, "Plot PWM 1", "Plotear y guardar los datos del PWM del Motor 1") self.Bind(wx.EVT_MENU, self.wxmPlotPWM1, m_PWM1) m_PWM2 = saveMenu.Append(-1, "Plot PWM 2", "Plotear y guardar los datos del PWM del Motor 2") self.Bind(wx.EVT_MENU, self.wxmPlotPWM2, m_PWM2) m_V1 = saveMenu.Append(-1, "Plot V1", "Plotear y guardar los datos de la velocidad del Motor 1") self.Bind(wx.EVT_MENU, self.wxmPlotV1, m_V1) m_V2 = saveMenu.Append(-1, "Plot V2", "Plotear y guardar los datos de la velocidad del Motor 2") self.Bind(wx.EVT_MENU, self.wxmPlotV2, m_V2) m_GPS = saveMenu.Append(-1, "Google Earth GPS", "Mostrar en Google Earth los datos del GPS") self.Bind(wx.EVT_MENU, self.googleEarth, m_GPS) m_Altitud = saveMenu.Append(-1, "Plot Altitud", "Plotear y guardar los datos de la Altitud") self.Bind(wx.EVT_MENU, self.wxmPlotAltitud, m_Altitud) m_Target = saveMenu.Append(-1, "Plot Target", "Plotear y guardar los datos de la distancia de la meta") self.Bind(wx.EVT_MENU, self.wxmPlotTarget, m_Target) #Dejemos en standby lo de posX y posY m_Estado = saveMenu.Append(-1, "Plot Estado", "Plotear y guardar los datos del Estado del Rover") self.Bind(wx.EVT_MENU, self.wxmPlotEstado, m_Estado) m_Moviendose = saveMenu.Append(-1, "Plot Moviendose", "Plotear y guardar los datos del Estado del Movimiento del Rover") self.Bind(wx.EVT_MENU, self.wxmPlotMoviendose, m_Moviendose) m_Fix = saveMenu.Append(-1, "Plot GPS Fix", "Plotear y guardar los datos del Fix del GPS") self.Bind(wx.EVT_MENU, self.wxmPlotFix, m_Fix) self.menubar.Append(saveMenu, "Plotear Datos") self.SetMenuBar(self.menubar) #Se crea un panel, el q va a contener los graficos, se inicializan los #graficos y se imprimen en el panel self.p2 como una figura. def create_main_panel(self): self.init_plot() self.canvas = FigCanvas(self.p2, -1, self.fig) #Se crea la barra de estado que esta en la parte de abajo de la ventana def create_status_bar(self): self.statusbar = self.CreateStatusBar() #Texto que va en la barra de estado, se puede #cambiar por medio de eventos self.statusbar.SetStatusText("Sensors Monitoring") #Inicializando los graficos, aqui se utiliza mayormente #la libreria matplotlib #Se indican las propiedades de los graficos y otras cosas def init_plot(self): #Resolucion del grafico self.dpi = 100 #Se crea el objeto que va a tener el o los graficos, #se le indica la resolucion #y el tamano self.fig = Figure((11, 7.0), dpi=self.dpi) #Se le agrega un subplot a la figura llamada PWM, #Esta figura va a tener los datos de los 2 PWM #se indica que la figura #va a tener un arreglo de graficos 2x2 (fila x columna) y que subplot #PWM va a ser el primero de los dos subplots. self.PWM = self.fig.add_subplot(221) self.PWM2 = self.fig.add_subplot(221) self.PWM.set_axis_bgcolor('black') self.PWM.set_title('PWM', size=12) pylab.setp(self.PWM.get_xticklabels(), fontsize=8) pylab.setp(self.PWM.get_yticklabels(), fontsize=8) #Se plotean datos, pero por primera vez, #luego se actualizan con el timer self.plot_PWM = self.PWM.plot( self.datos[PWM1], linewidth=1, color=(1, 1, 0),)[0] self.plot_PWM2 = self.PWM2.plot( (self.datos[PWM2]), linewidth=1, color=(1, 0, 0),)[0] #Falta PWM2 self.PWM.legend([self.plot_PWM, self.plot_PWM2], ["PWM1", "PWM2"]) #Agregando plot de Brujula #Aqui van a ir ploteados los datos del angulo con respecto al norte #Y el angulo con respecto al goal self.Brujula = self.fig.add_subplot(222) self.BrujulaGoal = self.fig.add_subplot(222) self.Brujula.set_axis_bgcolor('black') self.Brujula.set_title('Angulos', size=12) pylab.setp(self.Brujula.get_xticklabels(), fontsize=8) pylab.setp(self.Brujula.get_yticklabels(), fontsize=8) self.plot_Brujula = self.Brujula.plot( self.datos[COMPASS], linewidth=1, color=(0, 0, 1),)[0] self.plot_BrujulaGoal = self.BrujulaGoal.plot( self.datos[COMPASSGOAL], linewidth=1, color=(1, 0, 1),)[0] self.Brujula.legend([self.plot_Brujula, self.plot_BrujulaGoal], ["Norte", "Meta"]) #Agregando plot de Velocidades self.Vel = self.fig.add_subplot(223) self.Vel2 = self.fig.add_subplot(223) self.Vel.set_axis_bgcolor('black') self.Vel.set_title('Velocidades', size=12) pylab.setp(self.Vel.get_xticklabels(), fontsize=8) pylab.setp(self.Vel.get_yticklabels(), fontsize=8) self.plot_Vel = self.Vel.plot( self.datos[V1], linewidth=1, color=(0, 1, 0),)[0] self.plot_Vel2 = self.Vel2.plot( self.datos[V2], linewidth=1, color=(1, 1, 0),)[0] self.Vel.legend([self.plot_Vel, self.plot_Vel2], ["M1", "M2"]) #Agregando plot de POS self.POS = self.fig.add_subplot(224) self.POS.set_axis_bgcolor('black') self.POS.set_title('Posiciones', size=12) pylab.setp(self.POS.get_xticklabels(), fontsize=8) pylab.setp(self.POS.get_yticklabels(), fontsize=8) self.plot_POS = self.POS.plot( self.datos[POSX], self.datos[POSY], linewidth=1, color=(0, 0, 1),)[0] def draw_plot(self): xmax_PWM = len(self.datos[PWM1]) if len(self.datos[PWM1]) > 50 else 50 xmin_PWM = xmax_PWM - 50 ymin_PWM = round(min(min(self.datos[PWM1]), min(self.datos[PWM2])), 0) - 1 ymax_PWM = round(max(max(self.datos[PWM1]), max(self.datos[PWM2])), 0) + 1 #SACAR EL MINIMO Y MAX DE 2 ARRAYS, PWM1 Y PWM2 self.PWM.set_xbound(lower=xmin_PWM, upper=xmax_PWM) self.PWM.set_ybound(lower=ymin_PWM, upper=ymax_PWM) self.PWM.grid(True, color='w') self.plot_PWM.set_xdata(np.arange(len(self.datos[PWM1]))) self.plot_PWM.set_ydata(np.array(self.datos[PWM1])) self.plot_PWM2.set_xdata(np.arange(len(self.datos[PWM2]))) self.plot_PWM2.set_ydata(np.array(self.datos[PWM2])) #Plot de Brujula xmax_Comp = len(self.datos[COMPASS]) \ if len(self.datos[COMPASS]) > 50 else 50 xmin_Comp = xmax_Comp - 50 ymin_Comp = round(min(min(self.datos[COMPASS]), min(self.datos[COMPASSGOAL])), 0) + 1 ymax_Comp = round(max(max(self.datos[COMPASS]), max(self.datos[COMPASSGOAL])), 0) + 1 #SACAR EL MINIMO DE COMPASS Y COMPASSGOAL self.Brujula.set_xbound(lower=xmin_Comp, upper=xmax_Comp) self.Brujula.set_ybound(lower=ymin_Comp, upper=ymax_Comp) self.Brujula.grid(True, color='w') self.plot_Brujula.set_xdata(np.arange(len(self.datos[COMPASS]))) self.plot_Brujula.set_ydata(np.array(self.datos[COMPASS])) self.plot_BrujulaGoal.set_xdata(np.arange(len(self.datos[COMPASSGOAL]))) self.plot_BrujulaGoal.set_ydata(np.array(self.datos[COMPASSGOAL])) #Plot de Velocidades xmax_Vel = len(self.datos[V1]) \ if len(self.datos[V1]) > 50 else 50 xmin_Vel = xmax_Vel - 50 ymin_Vel = round(min(min(self.datos[V1]), min(self.datos[V2])), 0) - 1 ymax_Vel = round(max(max(self.datos[V1]), max(self.datos[V2])), 0) + 1 self.Vel.set_xbound(lower=xmin_Vel, upper=xmax_Vel) self.Vel.set_ybound(lower=ymin_Vel, upper=ymax_Vel) self.Vel.grid(True, color='w') self.plot_Vel.set_xdata(np.arange(len(self.datos[V1]))) self.plot_Vel.set_ydata(np.array(self.datos[V1])) self.plot_Vel2.set_xdata(np.arange(len(self.datos[V2]))) self.plot_Vel2.set_ydata(np.array(self.datos[V2])) #Plot de POS xmax_POS = round(max(self.datos[POSX]), 0) - 1 xmin_POS = round(min(self.datos[POSX]), 0) - 1 ymin_POS = round(min(self.datos[POSY]), 0) - 1 ymax_POS = round(max(self.datos[POSY]), 0) + 1 self.POS.set_xbound(lower=xmin_POS, upper=xmax_POS) self.POS.set_ybound(lower=ymin_POS, upper=ymax_POS) self.POS.grid(True, color='w') self.plot_POS.set_xdata(np.array(self.datos[POSX])) self.plot_POS.set_ydata(np.array(self.datos[POSY])) #Dibujando Plot self.canvas.draw() def on_save_plot(self, event): file_choices = "PNG (*.png)|*.png" dlg = wx.FileDialog( self, message="Save plot as...", defaultDir=os.getcwd(), defaultFile="plot.png", wildcard=file_choices, style=wx.SAVE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.canvas.print_figure(path, dpi=self.dpi) self.flash_status_message("Saved to %s" % path) def on_redraw_timer(self, event): wx.Yield() if not self.Pause: tempDatos = self.dataAQ.get() for i in range(15): self.datos[i].append(tempDatos[i]) self.logger.AppendText(("%0.10f" % tempDatos[LATITUD]) + "\t" + ("%0.10f" % tempDatos[LONGITUD]) + "\n") self.textoAltura.SetLabel(str(tempDatos[ALTITUD])) self.textoDistancia.SetLabel(str(tempDatos[TARGET])) self.textoEstado.SetLabel(str(tempDatos[ESTADO])) self.textoMoviendose.SetLabel(str(tempDatos[MOVIENDOSE])) self.textoFix.SetLabel(str(tempDatos[FIX])) self.draw_plot() def on_exit(self, event): self.Destroy() def getPath(self): strTime = (str(time.localtime()[0]) + "-" + str(time.localtime()[1]) + "-" + str(time.localtime()[2]) + "_" + str(time.localtime()[3]) + ":" + str(time.localtime()[4])) path = 'Datos_{}'.format(strTime) return path def saveData(self, event): #En esta funcion se van a guardar todos los datos que entran en un .txt #Los datos son: #COMPASS, PWM1, PWM2, V1, V2, LATITUD, LONGITUD, ALTITUD, COMPASSGOAL, #TARGET, POSX, POSY, ESTADO, MOVIENDOSE, FIX newpath = self.getPath() if not os.path.exists(newpath): os.makedirs(newpath) brujulaPath = newpath + "/datos_Brujula.txt" brujulaGoalPath = newpath + "/datos_BrujulaGoal.txt" PWM1Path = newpath + "/datos_PWM1.txt" PWM2Path = newpath + "/datos_PWM2.txt" V1Path = newpath + "/datos_V1.txt" V2Path = newpath + "/datos_V2.txt" GPSPath = newpath + "/datos_GPS.txt" self.GPSKMLPath = newpath + "/datos_GPS.kml" AltitudPath = newpath + "/datos_Altitud.txt" TargetPath = newpath + "/datos_Target.txt" PosPath = newpath + "/datos_POS.txt" EstadoPath = newpath + "/datos_Estado.txt" MoviendosePath = newpath + "/datos_Moviendose.txt" FixPath = newpath + "/datos_Fix.txt" self.fileBrujula = open(brujulaPath, 'w') self.fileBrujula.write("#Datos de Brujula\n") for i in range(len(self.datos[COMPASS])): txt = str(i) + '\t' + str(self.datos[COMPASS][i]) + '\n' self.fileBrujula.write(txt) self.fileBrujula.close() self.fileBrujulaGoal = open(brujulaGoalPath, 'w') self.fileBrujulaGoal.write("#Datos de BrujulaGoal\n") for i in range(len(self.datos[COMPASSGOAL])): txt = str(i) + '\t' + str(self.datos[COMPASSGOAL][i]) + '\n' self.fileBrujulaGoal.write(txt) self.fileBrujulaGoal.close() self.filePWM1 = open(PWM1Path, 'w') self.filePWM1.write("#Datos de PWM de Motor 1\n") for i in range(len(self.datos[PWM1])): txt = str(i) + '\t' + str(self.datos[PWM1][i]) + '\n' self.filePWM1.write(txt) self.filePWM1.close() self.filePWM2 = open(PWM2Path, 'w') self.filePWM2.write("#Datos de PWM de Motor 2\n") for i in range(len(self.datos[PWM2])): txt = str(i) + '\t' + str(self.datos[PWM2][i]) + '\n' self.filePWM2.write(txt) self.filePWM2.close() self.fileV1 = open(V1Path, 'w') self.fileV1.write("#Datos de velocidad del motor 1\n") for i in range(len(self.datos[V1])): txt = str(i) + '\t' + str(self.datos[V1][i]) + '\n' self.fileV1.write(txt) self.fileV1.close() self.fileV2 = open(V2Path, 'w') self.fileV2.write("#Datos de Velocidad del motor 2\n") for i in range(len(self.datos[V2])): txt = str(i) + '\t' + str(self.datos[V2][i]) + '\n' self.fileV2.write(txt) self.fileV2.close() self.fileAltitud = open(AltitudPath, 'w') self.fileAltitud.write("#Datos de Altitud dada por el barometro\n") for i in range(len(self.datos[ALTITUD])): txt = str(i) + '\t' + str(self.datos[ALTITUD][i]) + '\n' self.fileAltitud.write(txt) self.fileAltitud.close() self.fileTarget = open(TargetPath, 'w') self.fileTarget.write("#Datos de la distancia de la meta\n") for i in range(len(self.datos[TARGET])): txt = str(i) + '\t' + str(self.datos[TARGET][i]) + '\n' self.fileTarget.write(txt) self.fileTarget.close() self.filePOS = open(PosPath, 'w') self.filePOS.write("#Datos de la posicion en X y en Y\n") for i in range(len(self.datos[POSX])): txt = str(self.datos[POSX][i]) + \ '\t' + str(self.datos[POSY][i]) + '\n' self.filePOS.write(txt) self.filePOS.close() self.fileEstado = open(EstadoPath, 'w') self.fileEstado.write("#Datos del estado del Rover\n") for i in range(len(self.datos[ESTADO])): txt = str(i) + '\t' + str(self.datos[ESTADO][i]) + '\n' self.fileEstado.write(txt) self.fileEstado.close() self.fileMoviendose = open(MoviendosePath, 'w') self.fileMoviendose.write("#Datos binarios del movimiento del Rover\n") for i in range(len(self.datos[MOVIENDOSE])): txt = str(i) + '\t' + str(self.datos[MOVIENDOSE][i]) + '\n' self.fileMoviendose.write(txt) self.fileMoviendose.close() self.fileFix = open(FixPath, 'w') self.fileFix.write("#Datos del Fix del GPS\n") for i in range(len(self.datos[FIX])): txt = str(i) + '\t' + str(self.datos[FIX][i]) + '\n' self.fileFix.write(txt) self.fileFix.close() self.fileGPS = open(GPSPath, 'w') self.fileGPS.write("#Datos del GPS\n") for i in range(len(self.datos[LATITUD])): txt = str(self.datos[LATITUD][i]) +\ '\t' + str(self.datos[LONGITUD][i]) + '\n' self.fileGPS.write(txt) self.fileGPS.close() #GUARDANDO DATOS EN .KML kml = '<Placemark><LineString><coordinates>' for i in range(len(self.datosGPS[1])): kml += '\n' + str(self.datosGPS[1][i]) + \ ',' + str(self.datosGPS[0][i]) #for i in range(len(self.datos[LATITUD])): #kml += '\n' + str(self.datos[LONGITUD][i]) + \ #',' + str(self.datos[LATITUD][i]) kml += '\n </coordinates></LineString></Placemark>' with open(self.GPSKMLPath, 'w+') as data_file: data_file.write(kml) data_file.flush() self.flash_status_message("Guardado en %s" % newpath) def googleEarth(self, event): os.system("banner GOOGLE EARTH") command = "gnome-open " + self.GPSKMLPath os.system(command) def wxmPlotBrujula(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[COMPASS]), 1) self.plotframe.plot(ndato, self.datos[COMPASS], color='red', title='Datos Brujula') def wxmPlotBrujulaGoal(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[COMPASSGOAL]), 1) self.plotframe.plot(ndato, self.datos[COMPASSGOAL], color='red', title='Datos BrujulaGoal') def wxmPlotPWM1(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[PWM1]), 1) self.plotframe.plot(ndato, self.datos[PWM1], color='red', title='Datos PWM 1') def wxmPlotPWM2(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[PWM2]), 1) self.plotframe.plot(ndato, self.datos[PWM2], color='red', title='Datos PWM 2') def wxmPlotV1(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[V1]), 1) self.plotframe.plot(ndato, self.datos[V1], color='red', title='Datos V1') def wxmPlotV2(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[V2]), 1) self.plotframe.plot(ndato, self.datos[V2], color='red', title='Datos V2') def wxmPlotAltitud(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[ALTITUD]), 1) self.plotframe.plot(ndato, self.datos[ALTITUD], color='red', title='Datos Altitud') def wxmPlotTarget(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[TARGET]), 1) self.plotframe.plot(ndato, self.datos[TARGET], color='red', title='Datos distancia de la Meta') def wxmPlotEstado(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[ESTADO]), 1) self.plotframe.plot(ndato, self.datos[ESTADO], color='red', title='Datos Estado del Rover') def wxmPlotMoviendose(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[MOVIENDOSE]), 1) self.plotframe.plot(ndato, self.datos[MOVIENDOSE], color='red', title='Datos Estado del movimiento del Rover') def wxmPlotFix(self, event): self.ShowPlotFrame() ndato = np.arange(0, len(self.datos[FIX]), 1) self.plotframe.plot(ndato, self.datos[FIX], color='red', title='Datos del FIX del GPS') def flash_status_message(self, msg, flash_len_ms=1500): self.statusbar.SetStatusText(msg) self.timeroff = wx.Timer(self) self.Bind( wx.EVT_TIMER, self.on_flash_status_off, self.timeroff) self.timeroff.Start(flash_len_ms, oneShot=True) def on_flash_status_off(self, event): self.statusbar.SetStatusText('Sensors Monitoring')
class XAFSviewerFrame(wx.Frame): def __init__(self, parent=None, *args, **kwds): #kwds["style"] = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.TAB_TRAVERSAL wx.Frame.__init__(self, parent, wx.NewId(), '', wx.DefaultPosition, wx.Size(-1, -1), **kwds) #self.SetTitle(" WXMPlot Plotting Demo") """ self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False)) menu = wx.Menu() ID_EXIT = wx.NewId() ID_TIMER = wx.NewId() menu.Append(ID_EXIT, "E&xit", "Terminate the program") menuBar = wx.MenuBar() menuBar.Append(menu, "&File") self.SetMenuBar(menuBar) wx.EVT_MENU(self, ID_EXIT, self.OnExit) self.Bind(wx.EVT_CLOSE, self.OnExit) """ self.plotframe = None """ framesizer = wx.BoxSizer(wx.VERTICAL) panel = wx.Panel(self, -1, size=(-1, -1)) panelsizer = wx.BoxSizer(wx.VERTICAL) panelsizer.Add(wx.StaticText(panel, -1, 'XAFS Spectra viewer '), 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT | wx.EXPAND, 10) b40 = wx.Button(panel, -1, 'Start Timed Plot', size=(-1, -1)) #b40.Bind(wx.EVT_BUTTON,self.onStartTimer) panelsizer.Add(b40, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panel.SetSizer(panelsizer) panelsizer.Fit(panel) framesizer.Add(panel, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.EXPAND, 2) self.SetSizer(framesizer) framesizer.Fit(self) """ #----------- added by LWW ----------------------------- #====== self.showPlotFrame(do_raise=False, clear=False) """ self.plotYdata = [] self.plotXdata = [] # ----------epics PVs----------------------- self.i0 = PV('BL10C:scaler1_calc2.VAL') self.it = PV('BL10C:scaler1_calc3.VAL') self.iF = PV('BL10C:scaler1_calc4.VAL') self.trans = PV('BL10C:scaler1_calc8.VAL') self.motorPos = PV('mobiis:m2.RBV') self.scanStart = PV('lww:scan2.EXSC.VAL', callback=self.scanStartCALLBACK) while self.motorPos.get() is None: print self.motorPos.get() self.countDonePV = PV('BL10C:scaler1.CNT', callback=self.countDoneCALLBACK) """ self.time0 = time.time() self.datrange = None #----------- end of add by LWW ----------------------- #wx.EVT_TIMER(self, ID_TIMER, self.onTimer) #self.timer = wx.Timer(self, ID_TIMER) """ self.Refresh() """ # --------------epics callback method--------------------- def scanStartCALLBACK(self, **kwargs): if kwargs['value'] is 1: # 0:Done, 1: scanning self.showPlotFrame(do_raise=True, clear=False) print 'New Scan Started!!!' else: print 'scan stopped!!!' return def countDoneCALLBACK(self, **kwargs): """ if kwargs['value'] is 1: # 0:Done, 1:Counting return ## self._flag = True self.plotYdata.append(self.trans.get()) self.plotXdata.append(self.motorPos.get()) ## self._flag = False """ self.plotXdata = kwargs['plotXdata'] self.plotYdata = kwargs['plotYdata'] print 'X:%s, Y:%s' % (len(self.plotXdata), len(self.plotYdata)) # Todo: we need new scan start sequence. # new list, graph clear, data save..., # print 'timer ', self.count, time.time() ## self.count += 1 #self.showPlotFrame(do_raise=False, clear=False) ## n = self.count if len(self.plotXdata) < 2: return # Todo: implementation of scan finish sequence. ''' if n >= self.npts: self.timer.Stop() self.timer_results() elif n <= 3: ''' if len(self.plotXdata) <= 3: self.plotframe.plot(self.plotXdata, self.plotYdata, linewidth=0.5, marker='o', markersize=6, xlabel='energy[eV]', ylabel='[count]') # , grid=False) else: xx = np.array(self.plotXdata) yy = np.array(self.plotYdata) self.plotframe.update_line(0, xx, yy, update_limits=len(xx) < 10, draw=True) etime = time.time() - self.time0 s = " %i / %i points in %8.4f s" % (len(self.plotXdata), len(self.plotYdata), etime) self.plotframe.write_message(s) if self.datrange is None: self.datrange = [min(self.plotXdata), max(self.plotXdata), min(self.plotYdata), max(self.plotYdata)] dr = [min(self.plotXdata), max(self.plotXdata), min(self.plotYdata), max(self.plotYdata)] lims = self.plotframe.panel.get_viewlimits() if dr[0] < lims[0] or dr[1] > lims[1] or dr[2] < lims[2] or dr[3] > lims[3]: self.datrange = dr ## if len(self.plotXdata) < len(self.x): ## nmax = min(int(n*1.6), len(self.x)-1) ## self.datrange[1] = self.x[nmax] self.plotframe.panel.set_xylims(self.datrange) def showPlotFrame(self, do_raise=True, clear=True): """make sure plot frame is enabled, and visible""" if self.plotframe is None: self.plotframe = PlotFrame(self, axissize=[0.08, 0.06, 0.91, 0.92]) # self.has_plot = False try: self.plotframe.Show() except wx.PyDeadObjectError: self.plotframe = PlotFrame(self, axissize=[0.08, 0.06, 0.91, 0.92]) self.plotframe.Show() if do_raise: self.plotframe.Raise() ''' if clear: self.plotframe.panel.clear() self.plotframe.reset_config() self.plotYdata = [] self.plotXdata = [] ''' if clear is True: self.clearPlot() def clearPlot(self): self.plotframe.panel.clear() self.plotframe.reset_config() self.plotYdata = [] self.plotXdata = [] ''' def onStartTimer(self,event=None): self.count = 0 self.up_count = 0 self.n_update = 1 self.datrange = None self.time0 = time.time() ### LWW self.start_mem= self.report_memory() self.timer.Start(10) # self.timer.Start(500) def timer_results(self): if (self.count < 2): return etime = time.time() - self.time0 tpp = etime/max(1,self.count) s = "drew %i points in %8.3f s: time/point= %8.4f s" % (self.count,etime,tpp) self.plotframe.write_message(s) self.time0 = 0 self.count = 0 self.datrange = None ''' ''' def onTimer(self, event): # print 'timer ', self.count, time.time() self.count += 1 self.showPlotFrame(do_raise=False, clear=False) n = self.count if n < 2: return if n >= self.npts: self.timer.Stop() self.timer_results() elif n <= 3: self.plotframe.plot(self.x[:n], self.y1[:n])# , grid=False) else: self.plotframe.update_line(0, self.x[:n], self.y1[:n], update_limits=n<10, draw=True) etime = time.time() - self.time0 s = " %i / %i points in %8.4f s" % (n,self.npts,etime) self.plotframe.write_message(s) if self.datrange is None: self.datrange = [min(self.x[:n]), max(self.x[:n]), min(self.y1[:n]),max(self.y1[:n])] dr = [min(self.x[:n]), max(self.x[:n]), min(self.y1[:n]), max(self.y1[:n])] lims = self.plotframe.panel.get_viewlimits() if dr[0] < lims[0] or dr[1] > lims[1] or dr[2] < lims[2] or dr[3] > lims[3]: self.datrange = dr if n < len(self.x): nmax = min(int(n*1.6), len(self.x)-1) self.datrange[1] = self.x[nmax] self.plotframe.panel.set_xylims(self.datrange) ''' def OnAbout(self, event): dlg = wx.MessageDialog(self, "This program shows MCA Spectra\n" "message dialog.", "About MPlot test", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def OnExit(self, event): """ # 1st. disconnect PV(s) self.countDonePV.clear_callbacks() self.i0.disconnect() self.it.disconnect() self.iF.disconnect() self.trans.disconnect() self.motorPos.disconnect() """ try: if self.plotframe is not None: self.plotframe.onExit() except: pass self.Destroy()
class EigerFrame(wx.Frame): """AreaDetector Display """ img_attrs = ('ArrayData', 'UniqueId_RBV') cam_attrs = ('Acquire', 'DetectorState_RBV', 'ArrayCounter', 'ArrayCounter_RBV', 'ThresholdEnergy', 'ThresholdEnergy_RBV', 'PhotonEnergy', 'PhotonEnergy_RBV', 'NumImages', 'NumImages_RBV', 'AcquireTime', 'AcquireTime_RBV', 'AcquirePeriod', 'AcquirePeriod_RBV', 'TriggerMode', 'TriggerMode_RBV') # plugins to enable enabled_plugins = ('image1', 'Over1', 'ROI1', 'JPEG1', 'TIFF1') def __init__(self, prefix=None, url=None, scale=1.0): self.ad_img = None self.ad_cam = None if prefix is None: dlg = SavedParameterDialog(label='Detector Prefix', title='Connect to Eiger Detector', configfile='.ad_eigerdisplay.dat') res = dlg.GetResponse() dlg.Destroy() if res.ok: prefix = res.value self.prefix = prefix self.fname = 'Eiger.tif' self.esimplon = None if url is not None and HAS_SIMPLON: self.esimplon = EigerSimplon(url, prefix=prefix + 'cam1:') self.lineplotter = None self.calib = {} self.integrator = None self.int_panel = None self.int_lastid = None self.contrast_levels = None self.scandb = None wx.Frame.__init__(self, None, -1, "Eiger500K Area Detector Display", style=wx.DEFAULT_FRAME_STYLE) self.buildMenus() self.buildFrame() wx.CallAfter(self.connect_escandb) def connect_escandb(self): if HAS_ESCAN and os.environ.get('ESCAN_CREDENTIALS', None) is not None: self.scandb = ScanDB() calib_loc = self.scandb.get_info('eiger_calibration') cal = self.scandb.get_detectorconfig(calib_loc) self.setup_calibration(json.loads(cal.text)) def buildFrame(self): sbar = self.CreateStatusBar(3, wx.CAPTION) # |wx.THICK_FRAME) self.SetStatusWidths([-1, -1, -1]) sfont = sbar.GetFont() sfont.SetWeight(wx.BOLD) sfont.SetPointSize(10) sbar.SetFont(sfont) self.SetStatusText('', 0) sizer = wx.GridBagSizer(3, 3) panel = self.panel = wx.Panel(self) pvpanel = PVConfigPanel(panel, self.prefix, display_pvs) wsize = (100, -1) lsize = (250, -1) start_btn = wx.Button(panel, label='Start', size=wsize) stop_btn = wx.Button(panel, label='Stop', size=wsize) free_btn = wx.Button(panel, label='Free Run', size=wsize) start_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='start')) stop_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='stop')) free_btn.Bind(wx.EVT_BUTTON, partial(self.onButton, key='free')) self.cmap_choice = wx.Choice(panel, size=(80, -1), choices=colormaps) self.cmap_choice.SetSelection(0) self.cmap_choice.Bind(wx.EVT_CHOICE, self.onColorMap) self.cmap_reverse = wx.CheckBox(panel, label='Reverse', size=(60, -1)) self.cmap_reverse.Bind(wx.EVT_CHECKBOX, self.onColorMap) self.show1d_btn = wx.Button(panel, label='Show 1D Integration', size=(200, -1)) self.show1d_btn.Bind(wx.EVT_BUTTON, self.onShowIntegration) self.show1d_btn.Disable() self.imagesize = wx.StaticText(panel, label='? x ?', size=(250, 30), style=txtstyle) self.contrast = ContrastChoice(panel, callback=self.set_contrast_level) def lin(len=200, wid=2, style=wx.LI_HORIZONTAL): return wx.StaticLine(panel, size=(len, wid), style=style) irow = 0 sizer.Add(pvpanel, (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(start_btn, (irow, 0), (1, 1), labstyle) sizer.Add(stop_btn, (irow, 1), (1, 1), labstyle) sizer.Add(free_btn, (irow, 2), (1, 1), labstyle) irow += 1 sizer.Add(lin(300), (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(self.imagesize, (irow, 0), (1, 3), labstyle) irow += 1 sizer.Add(wx.StaticText(panel, label='Color Map: '), (irow, 0), (1, 1), labstyle) sizer.Add(self.cmap_choice, (irow, 1), (1, 1), labstyle) sizer.Add(self.cmap_reverse, (irow, 2), (1, 1), labstyle) irow += 1 sizer.Add(self.contrast.label, (irow, 0), (1, 1), labstyle) sizer.Add(self.contrast.choice, (irow, 1), (1, 1), labstyle) irow += 1 sizer.Add(self.show1d_btn, (irow, 0), (1, 2), labstyle) panel.SetSizer(sizer) sizer.Fit(panel) # image panel self.image = ADMonoImagePanel(self, prefix=self.prefix, rot90=DEFAULT_ROTATION, size=(400, 750), writer=partial(self.write, panel=2)) mainsizer = wx.BoxSizer(wx.HORIZONTAL) mainsizer.Add(panel, 0, wx.LEFT | wx.GROW | wx.ALL) mainsizer.Add(self.image, 1, wx.CENTER | wx.GROW | wx.ALL) self.SetSizer(mainsizer) mainsizer.Fit(self) self.SetAutoLayout(True) try: self.SetIcon(wx.Icon(ICONFILE, wx.BITMAP_TYPE_ICO)) except: pass wx.CallAfter(self.connect_pvs) def onColorMap(self, event=None): cmap_name = self.cmap_choice.GetStringSelection() if self.cmap_reverse.IsChecked(): cmap_name = cmap_name + '_r' self.image.colormap = getattr(colormap, cmap_name) self.image.Refresh() def onCopyImage(self, event=None): "copy bitmap of canvas to system clipboard" bmp = wx.BitmapDataObject() bmp.SetBitmap(wx.Bitmap(self.image.GrabWxImage())) wx.TheClipboard.Open() wx.TheClipboard.SetData(bmp) wx.TheClipboard.Close() wx.TheClipboard.Flush() def onReadCalibFile(self, event=None): "read calibration file" wcards = "Poni Files(*.poni)|*.poni|All files (*.*)|*.*" dlg = wx.FileDialog(None, message='Read Calibration File', defaultDir=os.getcwd(), wildcard=wcards, style=wx.FD_OPEN) ppath = None if dlg.ShowModal() == wx.ID_OK: ppath = os.path.abspath(dlg.GetPath()) if os.path.exists(ppath): if self.scandb is not None: CalibrationDialog(self, ppath).Show() else: self.setup_calibration(read_poni(ppath)) def setup_calibration(self, calib): """set up calibration from calibration dict""" if self.image.rot90 in (1, 3): calib['rot3'] = np.pi / 2.0 self.calib = calib if HAS_PYFAI: self.integrator = AzimuthalIntegrator(**calib) self.show1d_btn.Enable() def onShowIntegration(self, event=None): if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() def onAutoIntegration(self, event=None): if not event.IsChecked(): self.int_timer.Stop() return if self.calib is None or 'poni1' not in self.calib: return shown = False try: self.int_panel.Raise() shown = True except: self.int_panel = None if not shown: self.int_panel = PlotFrame(self) self.show_1dpattern(init=True) else: self.show_1dpattern() self.int_timer.Start(500) def show_1dpattern(self, init=False): if self.calib is None or not HAS_PYFAI: return img = self.ad_img.PV('ArrayData').get() h, w = self.image.GetImageSize() img.shape = (w, h) img = img[3:-3, 1:-1][::-1, :] img_id = self.ad_cam.ArrayCounter_RBV q, xi = self.integrator.integrate1d(img, 2048, unit='q_A^-1', correctSolidAngle=True, polarization_factor=0.999) if init: self.int_panel.plot(q, xi, xlabel=r'$Q (\rm\AA^{-1})$', marker='+', title='Image %d' % img_id) self.int_panel.Raise() self.int_panel.Show() else: self.int_panel.update_line(0, q, xi, draw=True) self.int_panel.set_title('Image %d' % img_id) @EpicsFunction def onSaveImage(self, event=None): "prompts for and save image to file" defdir = os.getcwd() self.fname = "Image_%i.tiff" % self.ad_cam.ArrayCounter_RBV dlg = wx.FileDialog(None, message='Save Image as', defaultDir=os.getcwd(), defaultFile=self.fname, style=wx.FD_SAVE) path = None if dlg.ShowModal() == wx.ID_OK: path = os.path.abspath(dlg.GetPath()) root, fname = os.path.split(path) epics.caput("%sTIFF1:FileName" % self.prefix, fname) epics.caput("%sTIFF1:FileWriteMode" % self.prefix, 0) time.sleep(0.05) epics.caput("%sTIFF1:WriteFile" % self.prefix, 1) time.sleep(0.05) print( "Saved TIFF File ", epics.caget("%sTIFF1:FullFileName_RBV" % self.prefix, as_string=True)) def onExit(self, event=None): try: wx.Yield() except: pass self.Destroy() def onAbout(self, event=None): msg = """Eiger Image Display version 0.1 Matt Newville <*****@*****.**>""" dlg = wx.MessageDialog(self, msg, "About Epics Image Display", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def buildMenus(self): fmenu = wx.Menu() MenuItem(self, fmenu, "&Save\tCtrl+S", "Save Image", self.onSaveImage) MenuItem(self, fmenu, "&Copy\tCtrl+C", "Copy Image to Clipboard", self.onCopyImage) MenuItem(self, fmenu, "Read Calibration File", "Read PONI Calibration", self.onReadCalibFile) fmenu.AppendSeparator() MenuItem(self, fmenu, "E&xit\tCtrl+Q", "Exit Program", self.onExit) omenu = wx.Menu() MenuItem(self, omenu, "&Rotate CCW\tCtrl+R", "Rotate Counter Clockwise", self.onRot90) MenuItem(self, omenu, "Flip Up/Down\tCtrl+T", "Flip Up/Down", self.onFlipV) MenuItem(self, omenu, "Flip Left/Right\tCtrl+F", "Flip Left/Right", self.onFlipH) MenuItem(self, omenu, "Reset Rotations and Flips", "Reset", self.onResetRotFlips) omenu.AppendSeparator() hmenu = wx.Menu() MenuItem(self, hmenu, "About", "About Epics AreadDetector Display", self.onAbout) mbar = wx.MenuBar() mbar.Append(fmenu, "File") mbar.Append(omenu, "Options") mbar.Append(hmenu, "&Help") self.SetMenuBar(mbar) def onResetRotFlips(self, event): self.image.rot90 = DEFAULT_ROTATION self.image.flipv = self.fliph = False def onRot90(self, event): self.image.rot90 = (self.image.rot90 - 1) % 4 def onFlipV(self, event): self.image.flipv = not self.image.flipv def onFlipH(self, event): self.image.fliph = not self.image.fliph def set_contrast_level(self, contrast_level=0): self.image.contrast_levels = [contrast_level, 100.0 - contrast_level] def write(self, s, panel=0): """write a message to the Status Bar""" self.SetStatusText(text=s, number=panel) @EpicsFunction def onButton(self, event=None, key='free'): key = key.lower() if key.startswith('free'): self.image.restart_fps_counter() self.ad_cam.AcquireTime = 0.25 self.ad_cam.AcquirePeriod = 0.25 self.ad_cam.NumImages = 345600 self.ad_cam.Acquire = 1 elif key.startswith('start'): self.image.restart_fps_counter() self.ad_cam.Acquire = 1 elif key.startswith('stop'): self.ad_cam.Acquire = 0 @EpicsFunction def connect_pvs(self, verbose=True): if self.prefix is None or len(self.prefix) < 2: return if self.prefix.endswith(':'): self.prefix = self.prefix[:-1] if self.prefix.endswith(':image1'): self.prefix = self.prefix[:-7] if self.prefix.endswith(':cam1'): self.prefix = self.prefix[:-5] self.write('Connecting to AD %s' % self.prefix) self.ad_img = epics.Device(self.prefix + ':image1:', delim='', attrs=self.img_attrs) self.ad_cam = epics.Device(self.prefix + ':cam1:', delim='', attrs=self.cam_attrs) epics.caput("%s:TIFF1:EnableCallbacks" % self.prefix, 1) epics.caput("%s:TIFF1:AutoSave" % self.prefix, 0) epics.caput("%s:TIFF1:AutoIncrement" % self.prefix, 0) epics.caput("%s:TIFF1:FileWriteMode" % self.prefix, 0) time.sleep(0.002) if not self.ad_img.PV('UniqueId_RBV').connected: epics.poll() if not self.ad_img.PV('UniqueId_RBV').connected: self.write('Warning: Camera seems to not be connected!') return if verbose: self.write('Connected to AD %s' % self.prefix) self.SetTitle("Epics Image Display: %s" % self.prefix) sizex = self.ad_cam.MaxSizeX_RBV sizey = self.ad_cam.MaxSizeY_RBV sizelabel = 'Image Size: %i x %i pixels' try: sizelabel = sizelabel % (sizex, sizey) except: sizelabel = sizelabel % (0, 0) self.imagesize.SetLabel(sizelabel) self.ad_cam.add_callback('DetectorState_RBV', self.onDetState) self.contrast.set_level_str('0.05') @DelayedEpicsCallback def onDetState(self, pvname=None, value=None, char_value=None, **kw): self.write(char_value, panel=1)
class TestFrame(wx.Frame): def __init__(self, parent=None, *args, **kwds): kwds[ "style"] = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.TAB_TRAVERSAL wx.Frame.__init__(self, parent, -1, '', wx.DefaultPosition, wx.Size(-1, -1), **kwds) self.SetTitle(" WXMPlot Plotting Demo") self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False)) menu = wx.Menu() menu_exit = menu.Append(-1, "E&xit", "Terminate the program") menuBar = wx.MenuBar() menuBar.Append(menu, "&File") self.SetMenuBar(menuBar) self.Bind(wx.EVT_MENU, self.OnExit, menu_exit) self.Bind(wx.EVT_CLOSE, self.OnExit) self.plotframe = None self.create_data() framesizer = wx.BoxSizer(wx.VERTICAL) panel = wx.Panel(self, -1, size=(-1, -1)) panelsizer = wx.BoxSizer(wx.VERTICAL) panelsizer.Add( wx.StaticText(panel, -1, 'wxmplot 2D PlotPanel examples '), 0, wx.ALIGN_LEFT | wx.LEFT | wx.EXPAND, 10) b10 = wx.Button(panel, -1, 'Example #1', size=(-1, -1)) b20 = wx.Button(panel, -1, 'Example #2', size=(-1, -1)) b22 = wx.Button(panel, -1, 'Plot with 2 axes', size=(-1, -1)) b31 = wx.Button(panel, -1, 'Plot with Errorbars', size=(-1, -1)) b32 = wx.Button(panel, -1, 'SemiLog Plot', size=(-1, -1)) b40 = wx.Button(panel, -1, 'Start Timed Plot', size=(-1, -1)) b50 = wx.Button(panel, -1, 'Stop Timed Plot', size=(-1, -1)) b60 = wx.Button(panel, -1, 'Plot 500,000 points', size=(-1, -1)) bmany1 = wx.Button(panel, -1, 'Plot 20 traces (delay_draw=False)', size=(-1, -1)) bmany2 = wx.Button(panel, -1, 'Plot 20 traces (delay_draw=True)', size=(-1, -1)) bmany3 = wx.Button(panel, -1, 'Plot 20 traces (use plot_many())', size=(-1, -1)) b10.Bind(wx.EVT_BUTTON, self.onPlot1) b20.Bind(wx.EVT_BUTTON, self.onPlot2) b22.Bind(wx.EVT_BUTTON, self.onPlot2Axes) b31.Bind(wx.EVT_BUTTON, self.onPlotErr) b32.Bind(wx.EVT_BUTTON, self.onPlotSLog) b40.Bind(wx.EVT_BUTTON, self.onStartTimer) b50.Bind(wx.EVT_BUTTON, self.onStopTimer) b60.Bind(wx.EVT_BUTTON, self.onPlotBig) bmany1.Bind(wx.EVT_BUTTON, self.onPlotMany_Slow) bmany2.Bind(wx.EVT_BUTTON, self.onPlotMany_Delay) bmany3.Bind(wx.EVT_BUTTON, self.onPlotMany_Fast) panelsizer.Add(b10, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b20, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b22, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b31, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b32, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b40, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b50, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(b60, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(bmany1, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(bmany2, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panelsizer.Add(bmany3, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5) panel.SetSizer(panelsizer) panelsizer.Fit(panel) framesizer.Add(panel, 0, wx.ALIGN_LEFT | wx.EXPAND, 2) self.SetSizer(framesizer) framesizer.Fit(self) self.Bind(wx.EVT_TIMER, self.onTimer) self.timer = wx.Timer(self) self.Refresh() def create_data(self): self.count = 0 self.x = x = arange(0.0, 25.0, 0.1) self.y1 = 4 * cos(2 * pi * (x - 1) / 5.7) / (6 + x) + 2 * sin( 2 * pi * (x - 1) / 2.2) / (10) self.y2 = sin(2 * pi * x / 30.0) self.y3 = -pi + 2 * (x / 10. + exp(-(x - 3) / 5.0)) self.y4 = exp(0.01 + 0.5 * x) / (x + 2) self.y5 = 3000 * self.y3 self.npts = len(self.x) self.bigx = linspace(0, 2500, 500000) self.bigy = (sin(pi * self.bigx / 140.0) + cos(pi * self.bigx / 277.0) + cos(pi * self.bigx / 820.0)) self.many_dlist = [(self.x, self.y1)] for i in range(19): self.many_dlist.append((self.x, sin(2 * (i + 1) * x / 23.0))) def ShowPlotFrame(self, do_raise=True, clear=True): "make sure plot frame is enabled, and visible" if self.plotframe is None: self.plotframe = PlotFrame(self) self.has_plot = False try: self.plotframe.Show() except PyDeadObjectError: self.plotframe = PlotFrame(self) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config() def onPlot1(self, event=None): self.ShowPlotFrame() self.plotframe.plot(self.x, self.y1) self.plotframe.oplot(self.x, self.y2) self.plotframe.write_message("Plot 1") def onPlot2(self, event=None): self.ShowPlotFrame() x = arange(100) y1 = cos(pi * x / 72) y2 = sin(pi * x / 23) self.plotframe.plot(x, y1, color='red') self.plotframe.oplot(x, y2, color='green3', marker='+') self.plotframe.write_message("Plot 2") def onPlotErr(self, event=None): self.ShowPlotFrame() npts = 81 x = linspace(0, 40.0, npts) y = 0.4 * cos(x / 2.0) + random.normal(scale=0.03, size=npts) dy = 0.03 * (ones(npts) + random.normal(scale=0.2, size=npts)) self.plotframe.plot(x, y, dy=dy, color='red', linewidth=0, xlabel='x', ylabel='y', marker='o', title='Plot with error bars') self.plotframe.write_message("Errorbars!") def onPlot2Axes(self, event=None): self.ShowPlotFrame() self.plotframe.plot(self.x, self.y2, color='black', style='dashed') self.plotframe.oplot(self.x, self.y5, color='red', side='right') self.plotframe.write_message("Plot with 2 axes") def onPlotSLog(self, event=None): self.ShowPlotFrame() self.plotframe.plot(self.x, self.y4, ylog_scale=True, color='black', style='dashed') self.plotframe.write_message("Semi Log Plot") def onPlotBig(self, event=None): self.ShowPlotFrame() t0 = time.time() self.plotframe.plot(self.bigx, self.bigy, marker='+', linewidth=0) dt = time.time() - t0 self.plotframe.write_message( "Plot array with npts=%i, elapsed time=%8.3f s" % (len(self.bigx), dt)) def onPlotMany_Slow(self, event=None): self.ShowPlotFrame() dlist = self.many_dlist t0 = time.time() opts = dict(title='Plot 20 traces without delay_draw', show_legend=True, xlabel='x') self.plotframe.plot(dlist[0][0], dlist[0][1], **opts) for tdat in dlist[1:]: self.plotframe.oplot(tdat[0], tdat[1]) dt = time.time() - t0 self.plotframe.write_message( "Plot 20 traces without delay_draw=True, elapsed time=%8.3f s" % (dt)) def onPlotMany_Delay(self, event=None): self.ShowPlotFrame() dlist = self.many_dlist t0 = time.time() opts = dict(title='Plot 20 traces with delay_draw', show_legend=True, xlabel='x') self.plotframe.plot(dlist[0][0], dlist[0][1], delay_draw=True, **opts) for tdat in dlist[1:-1]: self.plotframe.oplot(tdat[0], tdat[1], delay_draw=True) self.plotframe.oplot(dlist[-1][0], dlist[-1][1]) dt = time.time() - t0 self.plotframe.write_message( "Plot 20 traces with delay_draw=True, elapsed time=%8.3f s" % (dt)) def onPlotMany_Fast(self, event=None): self.ShowPlotFrame() dlist = self.many_dlist t0 = time.time() opts = dict(title='Plot 20 traces using plot_many()', show_legend=True, xlabel='x') self.plotframe.plot_many(dlist, **opts) dt = time.time() - t0 self.plotframe.write_message( "Plot 20 traces with plot_many(), elapsed time=%8.3f s" % (dt)) def report_memory(i): pid = os.getpid() if os.name == 'posix': mem = os.popen("ps -o rss -p %i" % pid).readlines()[1].split()[0] else: mem = 0 return int(mem) def onStartTimer(self, event=None): self.count = 0 self.up_count = 0 self.n_update = 1 self.datrange = None self.time0 = time.time() self.start_mem = self.report_memory() self.timer.Start(10) def timer_results(self): if (self.count < 2): return etime = time.time() - self.time0 tpp = etime / max(1, self.count) s = "drew %i points in %8.3f s: time/point= %8.4f s" % (self.count, etime, tpp) self.plotframe.write_message(s) self.time0 = 0 self.count = 0 self.datrange = None def onStopTimer(self, event=None): self.timer.Stop() try: self.timer_results() except: pass def onTimer(self, event): # print 'timer ', self.count, time.time() self.count += 1 n = self.count if n < 2: self.ShowPlotFrame(do_raise=False, clear=False) return if n >= self.npts: self.timer.Stop() self.timer_results() elif n <= 3: self.plotframe.plot(self.x[:n], self.y1[:n]) # , grid=False) else: self.plotframe.update_line(0, self.x[:n], self.y1[:n], update_limits=True, draw=True) etime = time.time() - self.time0 s = " %i / %i points in %8.4f s" % (n, self.npts, etime) self.plotframe.write_message(s) def OnAbout(self, event): dlg = wx.MessageDialog( self, "This sample program shows some\n" "examples of WXMPlot PlotFrame.\n" "message dialog.", "About WXMPlot test", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def OnExit(self, event): try: if self.plotframe != None: self.plotframe.onExit() except: pass self.Destroy()
class TestFrame(wx.Frame): def __init__(self, parent=None, *args,**kwds): kwds["style"] = wx.DEFAULT_FRAME_STYLE|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL wx.Frame.__init__(self, parent, -1, '', wx.DefaultPosition, wx.Size(-1,-1), **kwds) self.SetTitle(" WXMPlot Plotting Demo") self.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.BOLD,False)) menu = wx.Menu() menu_exit = menu.Append(-1, "E&xit", "Terminate the program") menuBar = wx.MenuBar() menuBar.Append(menu, "&File"); self.SetMenuBar(menuBar) self.Bind(wx.EVT_MENU, self.OnExit, menu_exit) self.Bind(wx.EVT_CLOSE, self.OnExit) self.plotframe = None self.create_data() framesizer = wx.BoxSizer(wx.VERTICAL) panel = wx.Panel(self, -1, size=(-1, -1)) panelsizer = wx.BoxSizer(wx.VERTICAL) panelsizer.Add( wx.StaticText(panel, -1, 'wxmplot 2D PlotPanel examples '), 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT|wx.EXPAND, 10) b10 = wx.Button(panel, -1, 'Example #1', size=(-1,-1)) b20 = wx.Button(panel, -1, 'Example #2', size=(-1,-1)) b22 = wx.Button(panel, -1, 'Plot with 2 axes', size=(-1,-1)) b31 = wx.Button(panel, -1, 'Plot with Errorbars', size=(-1,-1)) b32 = wx.Button(panel, -1, 'SemiLog Plot', size=(-1,-1)) b40 = wx.Button(panel, -1, 'Start Timed Plot', size=(-1,-1)) b50 = wx.Button(panel, -1, 'Stop Timed Plot', size=(-1,-1)) b60 = wx.Button(panel, -1, 'Plot 500,000 points', size=(-1,-1)) bmany1 = wx.Button(panel, -1, 'Plot 20 traces (delay_draw=False)', size=(-1,-1)) bmany2 = wx.Button(panel, -1, 'Plot 20 traces (delay_draw=True)', size=(-1,-1)) bmany3 = wx.Button(panel, -1, 'Plot 20 traces (use plot_many())', size=(-1,-1)) b10.Bind(wx.EVT_BUTTON,self.onPlot1) b20.Bind(wx.EVT_BUTTON,self.onPlot2) b22.Bind(wx.EVT_BUTTON,self.onPlot2Axes) b31.Bind(wx.EVT_BUTTON,self.onPlotErr) b32.Bind(wx.EVT_BUTTON,self.onPlotSLog) b40.Bind(wx.EVT_BUTTON,self.onStartTimer) b50.Bind(wx.EVT_BUTTON,self.onStopTimer) b60.Bind(wx.EVT_BUTTON,self.onPlotBig) bmany1.Bind(wx.EVT_BUTTON,self.onPlotMany_Slow) bmany2.Bind(wx.EVT_BUTTON,self.onPlotMany_Delay) bmany3.Bind(wx.EVT_BUTTON,self.onPlotMany_Fast) panelsizer.Add(b10, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(b20, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(b22, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(b31, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(b32, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(b40, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(b50, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(b60, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(bmany1, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(bmany2, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panelsizer.Add(bmany3, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 5) panel.SetSizer(panelsizer) panelsizer.Fit(panel) framesizer.Add(panel, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.EXPAND,2) self.SetSizer(framesizer) framesizer.Fit(self) self.Bind(wx.EVT_TIMER, self.onTimer) self.timer = wx.Timer(self) self.Refresh() def create_data(self): self.count = 0 self.x = x = arange(0.0,25.0,0.1) self.y1 = 4*cos(2*pi*(x-1)/5.7)/(6+x) + 2*sin(2*pi*(x-1)/2.2)/(10) self.y2 = sin(2*pi*x/30.0) self.y3 = -pi + 2*(x/10. + exp(-(x-3)/5.0)) self.y4 = exp(0.01 + 0.5*x ) / (x+2) self.y5 = 3000 * self.y3 self.npts = len(self.x) self.bigx = linspace(0, 2500, 500000) self.bigy = (sin(pi*self.bigx/140.0) + cos(pi*self.bigx/277.0) + cos(pi*self.bigx/820.0)) self.many_dlist = [(self.x, self.y1)] for i in range(19): self.many_dlist.append((self.x, sin(2*(i+1)*x/23.0))) def ShowPlotFrame(self, do_raise=True, clear=True): "make sure plot frame is enabled, and visible" if self.plotframe is None: self.plotframe = PlotFrame(self) self.has_plot = False try: self.plotframe.Show() except PyDeadObjectError: self.plotframe = PlotFrame(self) self.plotframe.Show() if do_raise: self.plotframe.Raise() if clear: self.plotframe.panel.clear() self.plotframe.reset_config() def onPlot1(self,event=None): self.ShowPlotFrame() self.plotframe.plot(self.x,self.y1) self.plotframe.oplot(self.x,self.y2) self.plotframe.write_message("Plot 1") def onPlot2(self,event=None): self.ShowPlotFrame() x = arange(100) y1 = cos(pi*x/72) y2 = sin(pi*x/23) self.plotframe.plot(x, y1, color='red') self.plotframe.oplot(x, y2, color='green3', marker='+') self.plotframe.write_message("Plot 2") def onPlotErr(self,event=None): self.ShowPlotFrame() npts = 81 x = linspace(0, 40.0, npts) y = 0.4 * cos(x/2.0) + random.normal(scale=0.03, size=npts) dy = 0.03 * (ones(npts) + random.normal(scale=0.2, size=npts)) self.plotframe.plot(x, y, dy=dy, color='red', linewidth=0, xlabel='x', ylabel='y', marker='o', title='Plot with error bars') self.plotframe.write_message("Errorbars!") def onPlot2Axes(self,event=None): self.ShowPlotFrame() self.plotframe.plot( self.x,self.y2, color='black',style='dashed') self.plotframe.oplot(self.x,self.y5, color='red', side='right') self.plotframe.write_message("Plot with 2 axes") def onPlotSLog(self,event=None): self.ShowPlotFrame() self.plotframe.plot( self.x,self.y4,ylog_scale=True, color='black',style='dashed') self.plotframe.write_message("Semi Log Plot") def onPlotBig(self,event=None): self.ShowPlotFrame() t0 = time.time() self.plotframe.plot(self.bigx, self.bigy, marker='+', linewidth=0) dt = time.time()-t0 self.plotframe.write_message( "Plot array with npts=%i, elapsed time=%8.3f s" % (len(self.bigx),dt)) def onPlotMany_Slow(self, event=None): self.ShowPlotFrame() dlist = self.many_dlist t0 = time.time() opts = dict(title='Plot 20 traces without delay_draw', show_legend=True, xlabel='x') self.plotframe.plot(dlist[0][0], dlist[0][1], **opts) for tdat in dlist[1:]: self.plotframe.oplot(tdat[0], tdat[1]) dt = time.time()-t0 self.plotframe.write_message( "Plot 20 traces without delay_draw=True, elapsed time=%8.3f s" % (dt)) def onPlotMany_Delay(self, event=None): self.ShowPlotFrame() dlist = self.many_dlist t0 = time.time() opts = dict(title='Plot 20 traces with delay_draw', show_legend=True, xlabel='x') self.plotframe.plot(dlist[0][0], dlist[0][1], delay_draw=True, **opts) for tdat in dlist[1:-1]: self.plotframe.oplot(tdat[0], tdat[1], delay_draw=True) self.plotframe.oplot(dlist[-1][0], dlist[-1][1]) dt = time.time()-t0 self.plotframe.write_message( "Plot 20 traces with delay_draw=True, elapsed time=%8.3f s" % (dt)) def onPlotMany_Fast(self, event=None): self.ShowPlotFrame() dlist = self.many_dlist t0 = time.time() opts = dict(title='Plot 20 traces using plot_many()', show_legend=True, xlabel='x') self.plotframe.plot_many(dlist, **opts) dt = time.time()-t0 self.plotframe.write_message( "Plot 20 traces with plot_many(), elapsed time=%8.3f s" % (dt)) def report_memory(i): pid = os.getpid() if os.name == 'posix': mem = os.popen("ps -o rss -p %i" % pid).readlines()[1].split()[0] else: mem = 0 return int(mem) def onStartTimer(self,event=None): self.count = 0 self.up_count = 0 self.n_update = 1 self.datrange = None self.time0 = time.time() self.start_mem= self.report_memory() self.timer.Start(10) def timer_results(self): if (self.count < 2): return etime = time.time() - self.time0 tpp = etime/max(1,self.count) s = "drew %i points in %8.3f s: time/point= %8.4f s" % (self.count,etime,tpp) self.plotframe.write_message(s) self.time0 = 0 self.count = 0 self.datrange = None def onStopTimer(self,event=None): self.timer.Stop() try: self.timer_results() except: pass def onTimer(self, event): # print 'timer ', self.count, time.time() self.count += 1 n = self.count if n < 2: self.ShowPlotFrame(do_raise=False, clear=False) return if n >= self.npts: self.timer.Stop() self.timer_results() elif n <= 3: self.plotframe.plot(self.x[:n], self.y1[:n])# , grid=False) else: self.plotframe.update_line(0, self.x[:n], self.y1[:n], update_limits=True, draw=True) etime = time.time() - self.time0 s = " %i / %i points in %8.4f s" % (n,self.npts,etime) self.plotframe.write_message(s) def OnAbout(self, event): dlg = wx.MessageDialog(self, "This sample program shows some\n" "examples of WXMPlot PlotFrame.\n" "message dialog.", "About WXMPlot test", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def OnExit(self, event): try: if self.plotframe != None: self.plotframe.onExit() except: pass self.Destroy()