#! /usr/bin/env mpscript # import wxversion wxversion.ensureMinimal("2.8") import numpy import wx import wxmpl import MpWx # # Create an object to hold attributes used by MpMultiMca. # class _MpMultiMca: pass _multi_mca = _MpMultiMca() _multi_mca.mxdir = mxdir # # Are we running a test version of MpMultiMca? # try: test = os.environ["MPMCATEST"] test = int(test) if ( test == 0 ): _multi_mca.test = False else: _multi_mca.test = True except: _multi_mca.test = False if ( _multi_mca.test ): lib_dir = os.getcwd() else: lib_dir = os.path.join( mxdir, "lib", "mpmca" ) lib_dir = os.path.normpath( lib_dir ) _multi_mca.lib_dir = lib_dir #-------------------------------------------------------------------------- if 1: _multi_mca.test = 1 if ( _multi_mca.test ): sys.path.append(".") import WxtSpinPanel #-------------------------------------------------------------------------- class MpMultiMca_App(wx.App): def OnInit( self ): # # _multi_mca.is_busy is used to remember whether the MCA # was busy the last time we checked, so we can compare # it to the current busy status. # _multi_mca.is_busy = False self.frame = MpMultiMca_MainFrame() self.frame.Show() self.SetTopWindow( self.frame ) self.timer = MpMultiMca_Timer( self ) _multi_mca.timer = self.timer ### self.timer.Start( 1000 ) self.timer.Start( 10 ) return True #-------------------------------------------------------------------------- def main( record_list, args ): _multi_mca.record_list = record_list _multi_mca.record_list.set_program_name('mpmca') if 0: _multi_mca.record_list.set_network_debug(True) # Construct an empty list of MCA information tuples. _multi_mca.mca_list = [] # Fill in the list for each MCA specified on the command line. for i in range( len(args) ): list_entry = MpMultiMca_ListEntry( record_list, args[i] ) _multi_mca.mca_list.append( list_entry ) # # Create the WxPython GUI. # app = MpMultiMca_App(redirect=False) _multi_mca.gui_ready = True # # Check to see if a site-specific script must be loaded. # load_site_script = False try: mx_site = record_list.get_record( "mx_site_mp_multi_mca" ) load_site_script = True except: pass if ( load_site_script ): mx_site_name = mx_site.get_field( "value" ) mx_site_script = \ os.path.join( _multi_mca.lib_dir, mx_site_name + ".py" ) execfile( mx_site_script ) # # Start the WxPython event loop. # app.MainLoop() #-------------------------------------------------------------------------- class MpMultiMca_ListEntry(): def __init__( self, record_list, mca_name ): self.name = mca_name self.fetch_spectrum = True self.record = record_list.get_record( mca_name ) # # Verify that the record we found is an MCA record. # mx_class = self.record.get_field( "mx_class" ) self.mca_type = self.record.get_field( "mx_type" ) if ( mx_class != "mca" ): msg = "Record '%s' is not an MCA record." \ " Instead, it is of type '%s'." \ % ( self.record.name, self.mca_type ) raise Mp.Type_Mismatch_Error, msg # # Certain record types require special handling. # if ( self.mca_type == "network_mca" ): server_record_name = \ self.record.get_field( "server_record" ) self.server_record = \ record_list.get_record( server_record_name ) self.remote_mca_name = \ self.record.get_field( "remote_record_name" ) mx_type_nf_name = "%s.mx_type" % (self.remote_mca_name) mx_type_nf = Mp.Net( self.server_record, mx_type_nf_name ) self.remote_mca_type = mx_type_nf.get() # # Create an Mp.Net object for the MCA spectrum. # self.channel_array_nf = Mp.Net( self.server_record, "%s.channel_array" % ( self.remote_mca_name ) ) else: pass #-------------------------------------------------------------------------- class MpMultiMca_ListEntryPanel(wx.Panel): def __init__( self, parent, list_entry ): wx.Panel.__init__( self, parent ) self.parent = parent self.list_entry = list_entry self.box = wx.BoxSizer( wx.HORIZONTAL ) self.SetSizer( self.box ) # # Create a tabbed notebook for this panel. # self.tab_notebook = MpMultiMca_Notebook( self ) self.box.Add( self.tab_notebook ) # # Create and add the Spectrum tab. # self.spectrum_tab = MpMultiMca_SpectrumTab( self.tab_notebook ) self.tab_notebook.AddPage( self.spectrum_tab, "Spectrum" ) # # Set up driver specific tabs. # mca_driver_setup_file = None if ( list_entry.remote_mca_type == "handel_mca" ): mca_driver_setup_file = "mpmca_handel_mca.py" if ( mca_driver_setup_file != None ): mca_driver_setup_file = os.path.join( _multi_mca.lib_dir, mca_driver_setup_file ) mca_driver_setup_file = \ os.path.normpath( mca_driver_setup_file ) print( "Loading mca_driver_setup_file '%s'" \ % ( mca_driver_setup_file ) ) execfile( mca_driver_setup_file, globals(), globals() ) MpMultiMca_DriverSetup( self ) self.Layout() #-------------------------------------------------------------------------- class MpMultiMca_Notebook(wx.Notebook): def __init__( self, parent ): wx.Notebook.__init__( self, parent ) self.parent = parent self.list_entry = parent.list_entry self.Bind( wx.EVT_SIZE, self.OnSize ) def OnSize( self, event ): # print( "MpMultiMca_Notebook: OnSize(): size = %s" \ # % self.GetSize() ) event.Skip() #-------------------------------------------------------------------------- class MpMultiMca_SpectrumTab(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.list_entry = parent.list_entry self.list_entry.spectrum_tab = self # # Create a GridBagSizer to contain the spectrum display, # and the controls window. # self.spectrum_tab_sizer = wx.GridBagSizer() # # Create the spectrum panel. # self.spectrum_panel = wxmpl.PlotPanel( self, -1 ) self.spectrum_tab_sizer.Add( self.spectrum_panel, pos=(0,0), border=10, flag=(wx.ALL | wx.EXPAND) ) # # Create the status and controls panel. # self.controls_panel = MpMultiMca_StatusAndControlsPanel( self ) self.spectrum_tab_sizer.Add( self.controls_panel, pos=(0,1), border=10, flag=(wx.ALL | wx.EXPAND) ) # # Attach spectrum_tab_sizer to the panel. # self.spectrum_tab_sizer.AddGrowableRow(0) self.spectrum_tab_sizer.AddGrowableCol(0) self.SetSizer( self.spectrum_tab_sizer ) self.Bind( wx.EVT_SIZE, self.OnSize ) def OnSize( self, event ): # print( "MpMultiMca_SpectrumTab: OnSize(): size = %s" \ # % self.GetSize() ) event.Skip() #============================================================================= class MpMultiMca_StatusAndControlsPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.list_entry = parent.list_entry self.spectrum_tab = parent self.box = wx.BoxSizer( wx.VERTICAL ) # # Create the status panel. # self.status_panel = MpMultiMca_StatusPanel( self ) self.box.Add( self.status_panel, border=5, flag=(wx.TOP | wx.BOTTOM | wx.ALIGN_LEFT) ) # # Create the control panel. # self.control_panel = MpMultiMca_ControlPanel( self ) self.box.Add( self.control_panel, border=5, flag=(wx.TOP | wx.BOTTOM | wx.ALIGN_LEFT) ) # # Create the control button panel. # self.control_button_panel = MpMultiMca_ControlButtonPanel( self ) self.box.Add( self.control_button_panel, border=5, flag=(wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER) ) # # Add the sizer to the panel. # self.SetSizer( self.box ) #------------------------------------------------------------------------------ def mpmca_real_time_update( nf, widget, args, value ): MpWx._Value_update( nf, widget, args, value ) list_entry = args list_entry.fetch_spectrum = True #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class MpMultiMca_StatusPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.list_entry = parent.list_entry self.spectrum_tab = parent.spectrum_tab self.grid = wx.GridBagSizer() status_width = 100 #-------- status_and_controls_panel = self.parent spectrum_tab = status_and_controls_panel.parent tab_notebook = spectrum_tab.parent list_entry_panel = tab_notebook.parent list_entry = list_entry_panel.list_entry self.list_entry = list_entry #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row = 0 self.name_label = wx.StaticText( self, -1, "MCA Name: " ) self.grid.Add( self.name_label, pos=(row,0) ) name_name = "%s.name" % ( list_entry.remote_mca_name ) self.name_value = MpWx.Value( self, list_entry.server_record, name_name, size=(status_width,-1) ) self.name_value.SetForegroundColour( "blue" ) self.grid.Add( self.name_value, pos=(row,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row = row + 1 self.spacer = wx.StaticText( self, -1, " " ) self.grid.Add( self.spacer, pos=(row,0) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row = row + 1 self.busy_label = wx.StaticText( self, -1, "Busy: " ) self.grid.Add( self.busy_label, pos=(row,0) ) busy_name = "%s.busy" % ( list_entry.remote_mca_name ) self.busy_value = MpWx.Value( self, list_entry.server_record, busy_name, size=(status_width,-1) ) self.busy_value.SetForegroundColour( "blue" ) self.grid.Add( self.busy_value, pos=(row,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row = row + 1 self.real_time_label = wx.StaticText( self, -1, "Real Time: " ) self.grid.Add( self.real_time_label, pos=(row,0) ) real_time_name = "%s.real_time" % ( list_entry.remote_mca_name ) self.real_time_value = MpWx.Value( self, list_entry.server_record, real_time_name, size=(status_width,-1), function=mpmca_real_time_update, args=list_entry ) self.real_time_value.SetForegroundColour( "blue" ) self.grid.Add( self.real_time_value, pos=(row,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row = row + 1 self.live_time_label = wx.StaticText( self, -1, "Live Time: " ) self.grid.Add( self.live_time_label, pos=(row,0) ) live_time_name = "%s.live_time" % ( list_entry.remote_mca_name ) self.live_time_value = MpWx.Value( self, list_entry.server_record, live_time_name, size=(status_width,-1) ) self.live_time_value.SetForegroundColour( "blue" ) self.grid.Add( self.live_time_value, pos=(row,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.Bind( wx.EVT_IDLE, self.OnIdle ) self.SetSizer( self.grid ) def OnIdle( self, event ): if ( self.list_entry.fetch_spectrum ): mpmca_get_spectrum_from_server( self.list_entry ) #------------------------------------------------------------------------------ def mpmca_get_spectrum_from_server( list_entry ): # print( "*** Getting spectrum from server for '%s' ***" \ # % ( list_entry.name ) ) spectrum_panel = list_entry.spectrum_tab.spectrum_panel figure = spectrum_panel.get_figure() axes = figure.gca() # Get the current MCA spectrum. spectrum = list_entry.channel_array_nf.get() numpy_spectrum = numpy.asarray( spectrum ) x_max = float( len(numpy_spectrum) ) x_axis = numpy.arange( 0.0, x_max, 1.0 ) # Clear the axes and replot everything. axes.cla() axes.plot( x_axis, numpy_spectrum ) axes.set_xlabel( "channel #" ) axes.set_ylabel( "counts" ) spectrum_panel.draw() list_entry.fetch_spectrum = False #------------------------------------------------------------------------------ def mpmca_preset_type_update( nf, widget, args, value ): widget.SetSelection( value ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class MpMultiMca_Choice(MpWx.Choice): def __init__( self, parent, server_record, field_name, choices=[] ): MpWx.Choice.__init__( self, parent, server_record, field_name, function=mpmca_preset_type_update, choices=choices ) original_value = self.nf.get() self.SetSelection( original_value ) self.Bind( wx.EVT_CHOICE, self.OnChoice ) def OnChoice( self, event ): selection = self.GetSelection() self.nf.put( selection ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class MpMultiMca_ControlPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.list_entry = parent.list_entry self.spectrum_tab = parent.spectrum_tab self.grid = wx.GridBagSizer() control_width = 40 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.preset_type_label = wx.StaticText( self, -1, "Preset Type: " ) self.grid.Add( self.preset_type_label, pos=(0,0), flag=wx.ALIGN_CENTER_VERTICAL ) #--- choices_list = ( "None", "Live Time", "Real Time", "Count" ) preset_type_name = "%s.preset_type" \ % ( self.list_entry.remote_mca_name ) self.preset_type_value = MpMultiMca_Choice( self, self.list_entry.server_record, preset_type_name, choices=choices_list ) self.grid.Add( self.preset_type_value, pos=(0,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.preset_real_time_label = wx.StaticText( self, -1, "Preset Real Time: " ) self.grid.Add( self.preset_real_time_label, pos=(1,0), flag=wx.ALIGN_CENTER_VERTICAL ) preset_real_time_name = "%s.preset_real_time" \ % ( self.list_entry.remote_mca_name ) self.preset_real_time_value = MpWx.ValueEntry( self, self.list_entry.server_record, preset_real_time_name, size=(100,-1) ) self.grid.Add( self.preset_real_time_value, pos=(1,1), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.preset_live_time_label = wx.StaticText( self, -1, "Preset Live Time: " ) self.grid.Add( self.preset_live_time_label, pos=(2,0), flag=wx.ALIGN_CENTER_VERTICAL ) preset_live_time_name = "%s.preset_live_time" \ % ( self.list_entry.remote_mca_name ) self.preset_live_time_value = MpWx.ValueEntry( self, self.list_entry.server_record, preset_live_time_name, size=(100,-1) ) self.grid.Add( self.preset_live_time_value, pos=(2,1), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.preset_count_label = wx.StaticText( self, -1, "Preset Count: " ) self.grid.Add( self.preset_count_label, pos=(3,0), flag=wx.ALIGN_CENTER_VERTICAL ) preset_count_name = "%s.preset_count" \ % ( self.list_entry.remote_mca_name ) self.preset_count_value = MpWx.ValueEntry( self, self.list_entry.server_record, preset_count_name, size=(100,-1) ) self.grid.Add( self.preset_count_value, pos=(3,1), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.SetSizer( self.grid ) #------------------------------------------------------------------------------ class MpMultiMca_ControlButtonPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.list_entry = parent.list_entry self.spectrum_tab = parent.spectrum_tab self.button_box = wx.BoxSizer( wx.HORIZONTAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.start_nf = Mp.Net( self.list_entry.server_record, "%s.start" % ( self.list_entry.remote_mca_name ) ) self.start_button = wx.Button( self, label="Start" ) if ( os.name == "nt" ): self.start_button.SetBackgroundColour( "green" ) else: self.start_button.SetBackgroundColour( "limegreen" ) self.Bind( wx.EVT_BUTTON, self.OnStartButton, self.start_button ) self.button_box.Add( self.start_button ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.spacer1 = wx.StaticText( self, -1, " " ) self.button_box.Add( self.spacer1 ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.stop_nf = Mp.Net( self.list_entry.server_record, "%s.stop" % ( self.list_entry.remote_mca_name ) ) self.stop_button = wx.Button( self, label="Stop" ) self.stop_button.SetBackgroundColour( "red" ) self.Bind( wx.EVT_BUTTON, self.OnStopButton, self.stop_button ) self.button_box.Add( self.stop_button ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.spacer2 = wx.StaticText( self, -1, " " ) self.button_box.Add( self.spacer2 ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.clear_nf = Mp.Net( self.list_entry.server_record, "%s.clear" % ( self.list_entry.remote_mca_name ) ) self.clear_button = wx.Button( self, label="Clear" ) self.clear_button.SetBackgroundColour( "gray" ) self.Bind( wx.EVT_BUTTON, self.OnClearButton, self.clear_button ) self.button_box.Add( self.clear_button ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.SetSizer( self.button_box ) def OnStartButton( self, event ): self.start_nf.put( 1 ) def OnStopButton( self, event ): self.stop_nf.put( 1 ) def OnClearButton( self, event ): self.clear_nf.put( 1 ) mpmca_get_spectrum_from_server() #============================================================================= # # The MpMultiMca_MainFrame class is used to implement the top level window # of mp_multi_mca. # # #----------------------------------------------------------------------------- # class MpMultiMca_MainFrame(wx.Frame): def __init__( self ): wx.Frame.__init__( self, None, \ title="MX Multi MCA Control" ) _multi_mca.frame = self # # Create a top level panel. # self.frame_panel = wx.Panel( self ) self.frame_panel.box = wx.BoxSizer( wx.VERTICAL ) self.frame_panel.SetSizer( self.frame_panel.box ) # # Create a panel to contain the WxtSpinPanel. # spin_panel = WxtSpinPanel.Panel( self.frame_panel ) self.frame_panel.spin_panel = spin_panel # # Add panels for each MCA to the spin panel. # for entry in _multi_mca.mca_list: panel = MpMultiMca_ListEntryPanel( spin_panel, entry ) spin_panel.AddPanel( panel, entry.name ) # # Initialize things to show the first panel. # spin_panel.SelectPanel( 0 ) # # Create and populate a menu bar. # self.menubar = MpMultiMca_MenuBar( self ) self.SetMenuBar( self.menubar ) # # Exit when the top level window is closed. # self.Bind( wx.EVT_CLOSE, self.OnCloseWindow ) self.Bind( wx.EVT_SIZE, self.OnSize ) # # Expand the size of the top level window to make sure # that all windows are visible. # self.Layout() def OnCloseWindow( self, event ): self.Destroy() def OnSize( self, event ): event.Skip() #----------------------------------------------------------------------------- class MpMultiMca_MenuBar(wx.MenuBar): def __init__( self, parent ): wx.MenuBar.__init__( self ) self.parent = parent #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Add the File menu. # self.file_menu = wx.Menu() self.Append( self.file_menu, "File" ) #--- exit_item = self.file_menu.Append( -1, "Exit" ) parent.Bind( wx.EVT_MENU, self.OnExit, exit_item ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Add the File menu. # self.help_menu = wx.Menu() self.Append( self.help_menu, "Help" ) about_item = self.help_menu.Append( -1, "About Mp_Multi_Mca" ) parent.Bind( wx.EVT_MENU, self.OnAbout, about_item ) def OnAbout( self, event ): dialog = MpMultiMca_AboutBox() dialog.ShowModal() dialog.Destroy() def OnExit( self, event ): _multi_mca.frame.Close( True ) #----------------------------------------------------------------------------- class MpMultiMca_AboutBox(wx.Dialog): def __init__( self ): wx.Dialog.__init__( self, None, -1, "About Mp_Multi_Mca" ) self.box = wx.BoxSizer( wx.VERTICAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.name = wx.StaticText( self, -1, "MX Multi MCA Control" ) self.box.Add( self.name, border=20, \ flag=(wx.ALL | wx.ALIGN_CENTER) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.copyright = wx.StaticText( self, -1, \ "Copyright 2013 Illinois Institute of Technology" ) self.box.Add( self.copyright, border=10, \ flag=(wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.author = wx.StaticText( self, -1, \ "Created by William M. Lavender" ) self.box.Add( self.author, border=10, \ flag=(wx.BOTTOM | wx.ALIGN_CENTER) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.button = wx.Button( self, label="OK" ) self.box.Add( self.button, border=10, \ flag=(wx.ALL | wx.ALIGN_CENTER) ) self.Bind( wx.EVT_BUTTON, self.OnOKButton, self.button ) self.SetSizer( self.box ) self.Fit() def OnOKButton( self, event ): self.Destroy() #============================================================================= # # The MpMultiMca_Timer class is used to implement periodic checks # of the hardware. # class MpMultiMca_Timer(wx.Timer): def __init__( self, owner ): wx.Timer.__init__( self, owner, id=-1 ) owner.Bind( wx.EVT_TIMER, self.OnTimerEvent, self ) def OnTimerEvent( self, timer_event ): # print( "vvv======= OnTimerEvent() invoked =======vvv" ) try: _multi_mca.record_list.wait_for_messages( 0.001 ) except Mp.Timed_Out_Error: pass # print( "^^^======= OnTimerEvent() complete ======^^^" ) #=============================================================================