#! /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 Mpmca. # class _Mpmca: pass _mpmca = _Mpmca() _mpmca.mxdir = mxdir # # Are we running a test version of Mpmca? # try: test = os.environ["MPMCATEST"] test = int(test) if ( test == 0 ): _mpmca.test = False else: _mpmca.test = True except: _mpmca.test = False if ( _mpmca.test ): lib_dir = os.getcwd() else: lib_dir = os.path.join( mxdir, "lib", "mpmca" ) lib_dir = os.path.normpath( lib_dir ) _mpmca.lib_dir = lib_dir #-------------------------------------------------------------------------- class MpmcaApp(wx.App): def OnInit( self ): # # _mpmca.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. # _mpmca.is_busy = False _mpmca.fetch_spectrum = False self.frame = MpmcaMainFrame() self.frame.Show() self.SetTopWindow( self.frame ) self.timer = MpmcaTimer( self ) _mpmca.timer = self.timer ### self.timer.Start( 1000 ) self.timer.Start( 10 ) return True #-------------------------------------------------------------------------- def main( record_list, args ): _mpmca.record_list = record_list _mpmca.record_list.set_program_name('mpmca') if 0: _mpmca.record_list.set_network_debug(True) # # Find the requested MCA. # if ( len(args) > 0 ): mca_name = args[0] _mpmca.mca_record = _mpmca.record_list.get_record( mca_name ) # # Verify that the record we found is an MCA record. # mx_class = _mpmca.mca_record.get_field("mx_class") mx_type = _mpmca.mca_record.get_field("mx_type") if ( mx_class != "mca" ): msg = "Record '%s' is not an MCA record." \ " Instead, it is of type '%s'." \ % ( _mpmca.mca_record.name, mx_type ) raise Mp.Type_Mismatch_Error, msg else: # Find the first MCA record in the MX database. list_head = _mpmca.record_list.get_record( "mx_database" ) current_record = list_head.get_next_record() while ( current_record != list_head ): mx_class = current_record.get_field("mx_class") # print( current_record.name, mx_class ) if ( mx_class == "mca" ): _mpmca.mca_record = current_record break current_record = current_record.get_next_record() try: _mpmca.mca_record except NameError: msg = "The MX database does not contain an MCA record." raise Mp.Not_Found_Error, msg print( "Using MCA record '%s'" % ( _mpmca.mca_record.name ) ) #------------------------------------------------------------------- # # What type of MCA record is this? # _mpmca.mx_type = _mpmca.mca_record.get_field("mx_type") # # If this is a network MCA record, find out what type of record # is being used by the server. # if ( _mpmca.mx_type != "network_mca" ): _mpmca.server_record = None _mpmca.remote_mca_name = None _mpmca.remote_mx_type = None else: server_record_name = \ _mpmca.mca_record.get_field("server_record") _mpmca.server_record = \ _mpmca.record_list.get_record( server_record_name ) _mpmca.remote_mca_name = \ _mpmca.mca_record.get_field("remote_record_name") mx_type_nf_name = "%s.mx_type" % ( _mpmca.remote_mca_name ) mx_type_nf = Mp.Net( _mpmca.server_record, mx_type_nf_name ) _mpmca.remote_mx_type = mx_type_nf.get() print( "_mpmca.remote_mx_type = %s" % _mpmca.remote_mx_type ) # # Create an Mp.Net object for the MCA spectrum. # _mpmca.channel_array_nf = Mp.Net( _mpmca.server_record, "%s.channel_array" % ( _mpmca.remote_mca_name ) ) # # Create the WxPython GUI. # app = MpmcaApp(redirect=False) _mpmca.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_mpmca" ) load_site_script = True except: pass if ( load_site_script ): mx_site_name = mx_site.get_field( "value" ) mx_site_script = \ os.path.join( _mpmca.lib_dir, mx_site_name + ".py" ) mx_site_script = os.path.normpath( mx_site_script ) execfile( mx_site_script ) # # Start the WxPython event loop. # app.MainLoop() #============================================================================= # # The MpmcaMainFrame class is used to implement the top level window of Mpmca. # # #---------------------------------------------------------------------------- # class MpmcaMainFrame(wx.Frame): def __init__( self ): wx.Frame.__init__( self, None, \ title="MX MCA Control" ) _mpmca.frame = self # # Create a panel to contain the notebook. # self.tab_panel = wx.Panel( self ) # # Create the tabbed notebook. # self.tab_notebook = MpmcaNotebook( self.tab_panel ) # # Create and add the Spectrum tab. # self.spectrum_tab = MpmcaSpectrumTab( self.tab_notebook ) self.tab_notebook.AddPage( self.spectrum_tab, "Spectrum" ) # # Set up driver specific tabs. # mca_driver_setup_file = None if ( _mpmca.remote_mx_type == "handel_mca" ): mca_driver_setup_file = "mpmca_handel_mca.py" if ( mca_driver_setup_file != None ): mca_driver_setup_file = os.path.join( \ _mpmca.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() ) MpmcaDriverSetup( self ) # # Create and populate a menu bar. # self.menubar = MpmcaMenuBar( 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 ) # # Create a Box sizer to contain the tab notebook. # self.tab_sizer = wx.BoxSizer( wx.HORIZONTAL ) self.tab_sizer.Add( self.tab_notebook, 1, wx.ALL|wx.EXPAND ) self.tab_panel.SetSizer( self.tab_sizer ) # # Expand the size of the top level window to make sure # that all windows are visible. # self.tab_panel.Fit() self.Fit() _mpmca.fetch_spectrum = True def OnCloseWindow( self, event ): self.Destroy() def OnSize( self, event ): # print( "MpmcaMainFrame: OnSize(): size = %s" % self.GetSize() ) event.Skip() #----------------------------------------------------------------------------- class MpmcaNotebook(wx.Notebook): def __init__( self, parent ): wx.Notebook.__init__( self, parent ) self.parent = parent self.Bind( wx.EVT_SIZE, self.OnSize ) def OnSize( self, event ): # print( "MpmcaNotebook: OnSize(): size = %s" % self.GetSize() ) event.Skip() #----------------------------------------------------------------------------- class MpmcaMenuBar(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 Mpmca" ) parent.Bind( wx.EVT_MENU, self.OnAbout, about_item ) def OnAbout( self, event ): dialog = MpmcaAboutBox() dialog.ShowModal() dialog.Destroy() def OnExit( self, event ): _mpmca.frame.Close( True ) #----------------------------------------------------------------------------- class MpmcaAboutBox(wx.Dialog): def __init__( self ): wx.Dialog.__init__( self, None, -1, "About Mpmca" ) self.box = wx.BoxSizer( wx.VERTICAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.name = wx.StaticText( self, -1, "MX MCA Control" ) self.box.Add( self.name, border=20, \ flag=(wx.ALL | wx.ALIGN_CENTER) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.copyright = wx.StaticText( self, -1, \ "Copyright 2012 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() #============================================================================= class MpmcaSpectrumTab(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent # # Create a GridBag sizer 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 = MpmcaStatusAndControlsPanel( 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( "MpmcaSpectrumTab: OnSize(): size =" % self.GetSize() ) event.Skip() #============================================================================= class MpmcaStatusAndControlsPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.box = wx.BoxSizer( wx.VERTICAL ) # # Create the status panel. # self.status_panel = MpmcaStatusPanel( self ) self.box.Add( self.status_panel, border=5, flag=(wx.TOP | wx.BOTTOM | wx.ALIGN_LEFT) ) # # Create the control panel. # self.control_panel = MpmcaControlPanel( 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 = MpmcaControlButtonPanel( 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 ) _mpmca.fetch_spectrum = True #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class MpmcaStatusPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.grid = wx.GridBagSizer() status_width = 100 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row = 0 self.name_label = wx.StaticText( self, -1, "MCA Name: " ) self.grid.Add( self.name_label, pos=(row,0) ) name_name = "%s.name" % ( _mpmca.remote_mca_name ) self.name_value = MpWx.Value( self, _mpmca.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" % ( _mpmca.remote_mca_name ) self.busy_value = MpWx.Value( self, _mpmca.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" % ( _mpmca.remote_mca_name ) self.real_time_value = MpWx.Value( self, _mpmca.server_record, real_time_name, size=(status_width,-1), function=mpmca_real_time_update ) 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" % ( _mpmca.remote_mca_name ) self.live_time_value = MpWx.Value( self, _mpmca.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 ( _mpmca.fetch_spectrum ): mpmca_get_spectrum_from_server() #------------------------------------------------------------------------------ def mpmca_get_spectrum_from_server(): # print( "*** Getting spectrum from server ***" ) spectrum_panel = _mpmca.frame.spectrum_tab.spectrum_panel figure = spectrum_panel.get_figure() axes = figure.gca() # Get the current MCA spectrum. spectrum = _mpmca.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() _mpmca.fetch_spectrum = False #------------------------------------------------------------------------------ def mpmca_preset_type_update( nf, widget, args, value ): widget.SetSelection( value ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class MpmcaChoice(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 MpmcaControlPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent 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" % ( _mpmca.remote_mca_name ) self.preset_type_value = MpmcaChoice( self, _mpmca.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" \ % ( _mpmca.remote_mca_name ) self.preset_real_time_value = MpWx.ValueEntry( self, _mpmca.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" \ % ( _mpmca.remote_mca_name ) self.preset_live_time_value = MpWx.ValueEntry( self, _mpmca.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" \ % ( _mpmca.remote_mca_name ) self.preset_count_value = MpWx.ValueEntry( self, _mpmca.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 MpmcaControlButtonPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.button_box = wx.BoxSizer( wx.HORIZONTAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.start_nf = Mp.Net( _mpmca.server_record, "%s.start" % ( _mpmca.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( _mpmca.server_record, "%s.stop" % ( _mpmca.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( _mpmca.server_record, "%s.clear" % ( _mpmca.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 MpmcaTimer class is used to implement periodic checks of the hardware. # class MpmcaTimer(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: _mpmca.record_list.wait_for_messages( 0.001 ) except Mp.Timed_Out_Error: pass # print( "^^^======= OnTimerEvent() complete ======^^^" ) #=============================================================================