#! /usr/bin/env mpscript # try: import wxversion wxversion.ensureMinimal("2.8") except: pass import numpy import time import wx import wx.lib.filebrowsebutton import wx.lib.stattext import MpNum import MpWx # # Have we been requested to start a C debugger? # try: test = os.environ["MPAD_DEBUGGER"] Mp.c_wait_for_debugger() except: pass #Mp.start_winpdb_debugger() # # Create an object to hold attributes used by Mpad. # class _Mpad: pass _mpad = _Mpad() _mpad.mxdir = mxdir _mpad.callback_list = [] _mpad.gui_ready = False _mpad.fetch_image_frame = False # Do we want a Python command entry window? _mpad.debug_window = True # Do we want to display a log of the serial communication with the camera head? _mpad.debug_serial = True # # Are we running a test version of Mpad? # try: test = os.environ["MPADTEST"] test = int(test) if ( test == 0 ): _mpad.test = False else: _mpad.test = True except: _mpad.test = False if ( _mpad.test ): lib_dir = os.getcwd() etc_dir = os.getcwd() else: lib_dir = os.path.join( mxdir, "lib", "mpad" ) lib_dir = os.path.normpath( lib_dir ) # etc_dir = os.path.join( mxdir, "etc" ) # etc_dir = os.path.normpath( etc_dir ) etc_dir = lib_dir _mpad.lib_dir = lib_dir _mpad.etc_dir = etc_dir sys.path.append( lib_dir ) #--- import WxtImage from MpadImage import * from MpadFloatValidator import * import MpadTools #-------------------------------------------------------------------------- class MpadApp(wx.App): def OnInit( self ): # # _mpad.is_busy is used to remember whether the area detector # was busy the last time we checked, so we can compare it to # the current busy status. # _mpad.is_busy = False self.frame = MpadMainFrame() self.frame.Show() self.SetTopWindow( self.frame ) self.timer = MpadTimer( self, _mpad.mx_database ) _mpad.timer = self.timer self.timer.Start( 1000 ) return True #-------------------------------------------------------------------------- def main( mx_database, args ): _mpad.mx_database = mx_database _mpad.mx_database.set_program_name('mpad') # _mpad.mx_database.set_network_debug( 3 ) # # Find the area detector record. # _mpad.ad_record = MpadTools.find_area_detector( mx_database, args ) #------------------------------------------------------------------- # # What type of area detector record is this? # ( _mpad.mx_type, _mpad.server_record, _mpad.remote_ad_name, _mpad.remote_mx_type ) \ = MpadTools.get_area_detector_type( _mpad.ad_record, mx_database ) print( "_mpad.remote_mx_type = '%s'" % _mpad.remote_mx_type ) # # Initialize the saved correction flags to 0, so that the Status # callback will ignore it (to begin with). # _mpad.saved_correction_flags = 0 # #------------------------------------------------------------------- # # Create the ImageFrame object that will be used to contain frames # read from the area detector. # maximum_framesize = _mpad.ad_record.get_maximum_framesize() bytes_per_pixel = _mpad.ad_record.get_bytes_per_pixel() _mpad.max_framesize = maximum_framesize num_pixels = int(maximum_framesize[0]) * int(maximum_framesize[1]) image_length = bytes_per_pixel * num_pixels image_length = int(image_length) image_frame = Mp.ImageFrame( maximum_framesize, \ _mpad.ad_record.get_image_format(), \ Mp.native_byteorder(), \ bytes_per_pixel, \ 0, \ image_length ) _mpad.image_frame = image_frame _mpad.ad_record.setup_frame( _mpad.image_frame ) _mpad.file_number = 0 # # Create the WxPython GUI. # app = MpadApp(redirect=False) _mpad.gui_ready = True # # Check to see if a site-specific script must be loaded. # try: mx_site = mx_database.get_record( "mx_site" ) mx_site_name = mx_site.get_field( "value" ) except: mx_site_name = "default" pass mx_site_script = \ os.path.join( _mpad.etc_dir, "site", mx_site_name + ".py" ) mx_site_script = os.path.normpath( mx_site_script ) try: # For Python 2 execfile( mx_site_script ) except NameError: # For Python 3 exec( open( mx_site_script ).read() ) except: print( "" ) print( "%s: Cannot execute MX site script '%s'." \ % ( mx_site_script ) ) traceback.print_exc() print( "" ) sys.exit(1) # # Start the WxPython event loop. # app.MainLoop() #============================================================================= # # The MpadMainFrame class is used to implement the top level window of Mpad. # # #---------------------------------------------------------------------------- # class MpadMainFrame(wx.Frame): def __init__( self ): wx.Frame.__init__( self, None, \ title="MX Area Detector Control" ) _mpad.frame = self # # Create a panel to contain the notebook. # self.tab_panel = wx.Panel( self ) # # Create the tabbed notebook. # self.tab_notebook = MpadNotebook( self.tab_panel ) # # Create and add the Image tab. # self.image_tab = MpadImageTab( self.tab_notebook ) self.tab_notebook.AddPage( self.image_tab, "Image" ) # # If available, create and add a Detector Controls tab. # detector_controls_file = None if ( _mpad.remote_mx_type == "pccd_170170" ): detector_controls_file = "mpad_pccd_170170.py" elif ( _mpad.remote_mx_type == "pccd_4824" ): detector_controls_file = "mpad_pccd_4824.py" elif ( _mpad.remote_mx_type == "pccd_9785" ): detector_controls_file = "mpad_pccd_9785.py" elif ( _mpad.remote_mx_type == "pccd_16080" ): detector_controls_file = "mpad_pccd_16080.py" if ( detector_controls_file != None ): detector_controls_file = os.path.join( \ _mpad.lib_dir, detector_controls_file ) detector_controls_file = os.path.normpath( \ detector_controls_file ) print ( "Loading detector_controls_file '%s'" \ % detector_controls_file ) execfile( detector_controls_file, globals(), globals() ) self.detector_controls_tab = \ MpadDetectorControlsTab( self.tab_notebook ) self.tab_notebook.AddPage( self.detector_controls_tab, \ "Detector Controls" ) self.setup_parameters_tab = \ MpadSetupParametersTab( self.tab_notebook ) self.tab_notebook.AddPage( self.setup_parameters_tab, \ "Setup Parameters" ) # # Create and populate a menu bar. # self.menubar = MpadMenuBar( 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 panel. # self.tab_sizer = wx.BoxSizer( wx.HORIZONTAL ) self.tab_sizer.Add( self.tab_notebook, 1, 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() def OnCloseWindow( self, event ): self.Destroy() def OnSize( self, event ): # print "MpadMainFrame: OnSize(): size =", self.GetSize() event.Skip() #----------------------------------------------------------------------------- class MpadNotebook(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 "MpadNotebook: OnSize(): size = ", self.GetSize() event.Skip() #----------------------------------------------------------------------------- class MpadMenuBar(wx.MenuBar): def __init__( self, parent ): wx.MenuBar.__init__( self ) self.parent = parent # # If we are connecting to a server that is on the same # machine as the client, then we suppress the client # image file menu entries. # ad_record_type = _mpad.ad_record.get_field("mx_type") if ( ad_record_type == "network_area_detector" ): server_record_name = \ _mpad.ad_record.get_field("server_record") server_record = \ _mpad.mx_database.get_record(server_record_name) server_type = server_record.get_field("mx_type") if ( server_type == "unix_server" ): show_client_items = False elif ( server_type == "tcp_server" ): hostname = server_record.get_field("hostname") if ( hostname == "localhost" ): show_client_items = False else: show_client_items = True else: show_client_items = True else: show_client_items = True # print "show_client_items =", show_client_items #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Add the File menu. # self.file_menu = wx.Menu() self.Append( self.file_menu, "File" ) if ( show_client_items ): load_image_item = \ self.file_menu.Append( -1, "Load Image File" ) parent.Bind( wx.EVT_MENU, \ self.OnLoadImage, load_image_item ) save_image_item = \ self.file_menu.Append( -1, "Save Image File" ) parent.Bind( wx.EVT_MENU, \ self.OnSaveImage, save_image_item ) self.file_menu.AppendSeparator() #--- load_server_item = self.file_menu.Append( -1, \ "Load Server Image" ) parent.Bind( wx.EVT_MENU, self.OnLoadServer, load_server_item ) save_server_item = self.file_menu.Append( -1, \ "Save Server Image" ) parent.Bind( wx.EVT_MENU, self.OnSaveServer, save_server_item ) self.file_menu.AppendSeparator() exit_item = self.file_menu.Append( -1, "Exit" ) parent.Bind( wx.EVT_MENU, self.OnExit, exit_item ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Add the Actions menu. # self.actions_menu = wx.Menu() self.Append( self.actions_menu, "Actions" ) get_server_frame_item = self.actions_menu.Append( -1, \ "Get Frame from Server" ) parent.Bind( wx.EVT_MENU, self.OnGetServerFrame, \ get_server_frame_item ) take_dark_frame_item = self.actions_menu.Append( -1, \ "Take Dark Current Image" ) parent.Bind( wx.EVT_MENU, self.OnTakeDarkFrame, \ take_dark_frame_item ) take_flat_frame_item = self.actions_menu.Append( -1, \ "Take Flat Field Image" ) parent.Bind( wx.EVT_MENU, self.OnTakeFlatFrame, \ take_flat_frame_item ) if ( _mpad.debug_window ): debug_window_item = self.actions_menu.Append( -1, \ "Debug Window" ) parent.Bind( wx.EVT_MENU, self.OnDebugWindow, \ debug_window_item ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Add the Help menu. # self.help_menu = wx.Menu() self.Append( self.help_menu, "Help" ) about_item = self.help_menu.Append( -1, "About Mpad" ) parent.Bind( wx.EVT_MENU, self.OnAbout, about_item ) def OnAbout( self, event ): dialog = MpadAboutBox() dialog.ShowModal() dialog.Destroy() def OnExit( self, event ): _mpad.frame.Close( True ) def OnGetServerFrame( self, event ): dialog = MpadGetServerFrameDialog() dialog.ShowModal() dialog.Destroy() def OnLoadImage( self, event ): dialog = wx.FileDialog( None, "Load Image File", style=wx.OPEN ) result = dialog.ShowModal() if ( result == wx.ID_OK ): filename = dialog.GetPath() _mpad.image_frame.read_file( Mp.MXT_IMAGE_FILE_SMV, \ filename ) mpad_image_panel = _mpad.frame.image_tab.mpad_image_panel mpad_image_panel.SetData( _mpad.image_frame ) mpad_image_panel.Display() dialog.Destroy() def OnLoadServer( self, event ): dialog = MpadLoadSaveServerDialog( 'load' ) dialog.ShowModal() dialog.Destroy() def OnSaveImage( self, event ): dialog = wx.FileDialog( None, "Save Image File", \ style=(wx.SAVE | wx.OVERWRITE_PROMPT) ) result = dialog.ShowModal() if ( result == wx.ID_OK ): filename = dialog.GetPath() _mpad.image_frame.write_file( Mp.MXT_IMAGE_FILE_SMV, \ filename ) dialog.Destroy() def OnSaveServer( self, event ): dialog = MpadLoadSaveServerDialog( 'save' ) dialog.ShowModal() dialog.Destroy() def OnTakeDarkFrame( self, event ): dialog = MpadDarkFlatDialog( 'dark' ) dialog.ShowModal() dialog.Destroy() def OnTakeFlatFrame( self, event ): dialog = MpadDarkFlatDialog( 'flat' ) dialog.ShowModal() dialog.Destroy() def OnDebugWindow( self, event ): # print "OnDebugWindow called" dialog = MpadDebugDialog() dialog.Show() #----------------------------------------------------------------------------- class MpadLoadSaveServerDialog(wx.Dialog): def __init__( self, loadsave ): self.server_frame_type = Mp.MXFT_AD_IMAGE_FRAME if ( loadsave == 'load' ): dialog_title = "Load Server Frame" elif ( loadsave == 'save' ): dialog_title = "Save Server Frame" else: self.Destroy() msg = "Bad loadsave argument '%s' supplied." % loadsave raise Mp.IllegalArgumentError( msg ) wx.Dialog.__init__( self, None, -1, dialog_title ) self.grid = wx.GridBagSizer( hgap=5, vgap=5 ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.frametype_label = wx.StaticText( self, -1, "Frame Type: " ) self.grid.Add( self.frametype_label, pos=(0,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) frametype_list = [ 'Image Frame', 'Mask Frame', 'Bias Frame', \ 'Dark Current Frame', 'Flat Field Frame' ] self.frametype_selector = wx.Choice( self, -1, \ choices=frametype_list ) self.grid.Add( self.frametype_selector, pos=(0,1) ) self.Bind( wx.EVT_CHOICE, self.OnChoice, \ self.frametype_selector ) # Setting the selection after we bind makes sure that # get_server_frame_type() has been invoked. self.frametype_selector.SetSelection(0) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.filename_label = wx.StaticText( self, -1, \ "Server Filename: " ) self.grid.Add( self.filename_label, pos=(1,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.filename_ctrl = wx.TextCtrl( self, size=(200,30) ) self.grid.Add( self.filename_ctrl, pos=(1,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Create a panel to put the buttons in. self.button_panel = MpadLoadSaveButtonPanel( self, loadsave ) self.grid.Add( self.button_panel, pos=(2,0), span=(1,2), \ flag=wx.ALIGN_CENTER ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.SetSizer( self.grid ) self.Fit() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def OnChoice( self, event ): selection = self.frametype_selector.GetSelection() self.server_frame_type = get_server_frame_type( selection ) #----------------------------------------------------------------------------- class MpadLoadSaveButtonPanel(wx.Panel): def __init__( self, parent, loadsave ): wx.Panel.__init__( self, parent ) self.parent = parent self.box = wx.BoxSizer( wx.HORIZONTAL ) if ( loadsave == 'load' ): self.loadsave_button = wx.Button( self, label="Load" ) self.Bind( wx.EVT_BUTTON, self.OnLoadButton, \ self.loadsave_button ) else: self.loadsave_button = wx.Button( self, label="Save" ) self.Bind( wx.EVT_BUTTON, self.OnSaveButton, \ self.loadsave_button ) self.box.Add( self.loadsave_button ) self.cancel_button = wx.Button( self, label="Cancel" ) self.Bind( wx.EVT_BUTTON, self.OnCancelButton, \ self.cancel_button ) self.box.Add( self.cancel_button ) self.SetSizer( self.box ) def OnLoadButton( self, event ): filename = self.parent.filename_ctrl.GetValue() if ( filename == None ): return elif ( filename == "" ): return _mpad.ad_record.load_frame( \ self.parent.server_frame_type, filename ) print ( "File '%s' loaded." % filename ) self.parent.Destroy() def OnSaveButton( self, event ): filename = self.parent.filename_ctrl.GetValue() if ( filename == None ): return elif ( filename == "" ): return _mpad.ad_record.save_frame( \ self.parent.server_frame_type, filename ) print ( "File '%s' saved." % filename ) self.parent.Destroy() def OnCancelButton( self, event ): self.parent.Destroy() #----------------------------------------------------------------------------- class MpadDarkFlatDialog(wx.Dialog): def __init__( self, darkflat ): self.measurement_type = darkflat if ( self.measurement_type == 'dark' ): dialog_title = "Take Dark Current Image" elif ( self.measurement_type == 'flat' ): dialog_title = "Take Flat Field Image" else: self.Destroy() msg = "Bad darkflat argument '%s' supplied." \ % dark_flat raise Mp.IllegalArgumentError( msg ) wx.Dialog.__init__( self, None, -1, dialog_title ) self.grid = wx.GridBagSizer( hgap=5, vgap=5 ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.num_label = wx.StaticText( self, -1, \ "Number of Measurements: " ) self.grid.Add( self.num_label, pos=(0,0), border=5, \ flag=(wx.LEFT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.num_ctrl = wx.TextCtrl( self ) self.grid.Add( self.num_ctrl, pos=(0,1), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.time_label = wx.StaticText( self, -1, "Measurement Time: ") self.grid.Add( self.time_label, pos=(1,0), border=5, \ flag=(wx.LEFT | wx.TOP | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.time_ctrl = wx.TextCtrl( self ) self.grid.Add( self.time_ctrl, pos=(1,1), border=5, \ flag=(wx.TOP | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.button_box = wx.BoxSizer( wx.HORIZONTAL ) self.grid.Add( self.button_box, pos=(2,0), span=(1,2), \ border=10, flag=(wx.ALL | wx.ALIGN_CENTER) ) self.start_button = wx.Button( self, label="Start Measurement" ) self.button_box.Add( self.start_button ) self.Bind( wx.EVT_BUTTON, self.OnStartButton, \ self.start_button ) self.cancel_button = wx.Button( self, label="Cancel" ) self.button_box.Add( self.cancel_button ) self.Bind( wx.EVT_BUTTON, self.OnCancelButton, \ self.cancel_button ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.SetSizer( self.grid ) self.Fit() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def OnCancelButton( self, event ): self.Destroy() def OnStartButton( self, event ): print ( "Start button pressed." ) measurement_time_string = self.time_ctrl.GetValue() if ( measurement_time_string == "" ): return num_measurements_string = self.num_ctrl.GetValue() if ( num_measurements_string == "" ): return measurement_time = float(measurement_time_string) num_measurements = int(num_measurements_string) if ( self.measurement_type == 'dark' ): print ( \ "Starting dark current measurement for area detector '%s'." \ % _mpad.ad_record.name ) print ( \ "Measurement time = %g seconds, number of measurements = %d" \ % ( measurement_time, num_measurements ) ) _mpad.ad_record.measure_dark_current_frame( \ measurement_time, num_measurements ) elif ( self.measurement_type == 'flat' ): print ( \ "Starting flat field measurement for area detector '%s'." \ % _mpad.ad_record.name ) print ( \ "Measurement time = %g seconds, number of measurements = %d" \ % ( measurement_time, num_measurements ) ) _mpad.ad_record.measure_flat_field_frame( \ measurement_time, num_measurements ) else: self.Destroy() msg = "Bad measurement type '%s' supplied." \ % self.measurement_type raise Mp.IllegalArgumentError( msg ) # # Wait for the measurement to complete. # # FIXME: We should have a progress meter and # an active cancel button here. # while True: _mpad.mx_database.wait_for_messages(0.1) busy = _mpad.ad_record.is_busy() if ( busy == False ): break time.sleep(0.1) print ( "Measurement complete." ) self.Destroy() #----------------------------------------------------------------------------- class MpadDebugDialog(wx.Dialog): def __init__( self ): wx.Dialog.__init__( self, None, -1, "Mpad Debug Window" ) self.grid = wx.GridBagSizer( hgap=5, vgap=5 ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.prompt_label = wx.StaticText( self, -1, ">>> " ) self.grid.Add( self.prompt_label, pos=(0,0), border=5, \ flag=(wx.LEFT | wx.TOP | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) # # style=wx.TE_PROCESS_ENTER must be specify if we want to # use events of type wx.EVT_TEXT_ENTER. # self.prompt_ctrl = wx.TextCtrl( self, size=(400,-1), \ style=wx.TE_PROCESS_ENTER ) self.prompt_ctrl.Bind( wx.EVT_TEXT_ENTER, self.OnEnter ) self.grid.Add( self.prompt_ctrl, pos=(0,1), border=5, \ flag=(wx.TOP | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.dismiss_button = wx.Button( self, label="Dismiss" ) self.Bind( wx.EVT_BUTTON, \ self.OnDismissButton, self.dismiss_button ) self.grid.Add( self.dismiss_button, pos=(1,0), span=(1,2), \ border=5, flag=wx.ALIGN_CENTER ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.SetSizer( self.grid ) self.Fit() def OnDismissButton( self, event ): self.Destroy() def OnEnter( self, event ): command = self.prompt_ctrl.GetValue() command = str(command) print ( "Command: %s" % command ) self.prompt_ctrl.SetValue("") if ( sys.version_info[0] < 3 ): exec( command in globals() ) else: exec( command, globals() ) print ( "Command complete." ) #----------------------------------------------------------------------------- class MpadGetServerFrameDialog(wx.Dialog): def __init__( self ): wx.Dialog.__init__( self, None, -1, "Get Server Frame" ) self.server_frame_type = Mp.MXFT_AD_IMAGE_FRAME self.grid = wx.GridBagSizer( hgap=5, vgap=5 ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.frametype_label = wx.StaticText( self, -1, "Frame Type: " ) self.grid.Add( self.frametype_label, pos=(0,0), border=10, \ flag=(wx.LEFT | wx.TOP | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) frametype_list = [ 'Image Frame', 'Mask Frame', 'Bias Frame', \ 'Dark Current Frame', 'Flat Field Frame' ] self.frametype_selector = wx.Choice( self, -1, \ choices=frametype_list ) self.grid.Add( self.frametype_selector, pos=(0,1), border=10, \ flag=(wx.RIGHT | wx.TOP) ) self.Bind( wx.EVT_CHOICE, self.OnChoice, \ self.frametype_selector ) # Setting the selection after we bind makes sure that # get_server_frame_type() has been invoked. self.frametype_selector.SetSelection(0) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.button_box = wx.BoxSizer( wx.HORIZONTAL ) self.get_frame_button = wx.Button( self, label="Get Frame" ) self.button_box.Add( self.get_frame_button ) self.Bind( wx.EVT_BUTTON, self.OnGetFrameButton, \ self.get_frame_button ) self.cancel_button = wx.Button( self, label="Cancel" ) self.button_box.Add( self.cancel_button ) self.Bind( wx.EVT_BUTTON, self.OnCancelButton, \ self.cancel_button ) self.grid.Add( self.button_box, pos=(1,0), span=(1,2), \ border=10, flag=(wx.ALL | wx.ALIGN_CENTER) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.SetSizer( self.grid ) self.Fit() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def OnChoice( self, event ): selection = self.frametype_selector.GetSelection() self.server_frame_type = get_server_frame_type( selection ) def OnCancelButton( self, event ): self.Destroy() def OnGetFrameButton( self, event ): _mpad.ad_record.transfer_frame( self.server_frame_type, \ _mpad.image_frame ) mpad_image_panel = _mpad.frame.image_tab.mpad_image_panel mpad_image_panel.SetData( _mpad.image_frame ) mpad_image_panel.Display() self.Destroy() #----------------------------------------------------------------------------- class MpadAboutBox(wx.Dialog): def __init__( self ): wx.Dialog.__init__( self, None, -1, "About Mpad" ) self.box = wx.BoxSizer( wx.VERTICAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.name = wx.StaticText( self, -1, "MX Area Detector Control") self.box.Add( self.name, border=20, \ flag=(wx.ALL | wx.ALIGN_CENTER) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.copyright = wx.StaticText( self, -1, \ "Copyright 2008-2016 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 MpadImageTab(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent # # Create a Box sizer to contain the main image and the # side window. # self.image_tab_sizer = wx.BoxSizer( wx.HORIZONTAL ) # # Attach image_tab_sizer to the panel. # #---------------------------- # # Create the image panel. # self.mpad_image_panel = MpadImagePanel( self ) self.image_tab_sizer.Add( self.mpad_image_panel, 1, \ border=10, flag=wx.EXPAND ) # # Create the right hand panel. # self.right_panel = MpadRightPanel( self ) # FIXME - Should we add wx.EXPAND for the right panel? self.image_tab_sizer.Add( self.right_panel, 0, \ border=10, flag=wx.ALL) self.SetSizer( self.image_tab_sizer ) self.Bind( wx.EVT_SIZE, self.OnSize ) def OnSize( self, event ): # print ( "MpadImageTab: OnSize(): size =", self.GetSize() ) event.Skip() #============================================================================= def mpad_monitor_display( field_name, widget, scale, offset, function, choices): nf_name = "%s.%s" % ( _mpad.ad_record.name, field_name ) nf = Mp.Net( _mpad.server_record, nf_name ) args = (nf, widget, function, choices) callback = nf.add_callback( Mp.MXCBT_VALUE_CHANGED, \ mpad_monitor_callback, args ) _mpad.callback_list.append( callback ) del callback return nf def mpad_monitor_callback( callback, args ): (nf, widget, function, choices) = args print ( "nf = '%s:%s', widget = %s, function = %s, choices = %s" \ % ( nf.server.name, nf.name, widget, function, choices ) ) if ( function != None ): function( nf, widget, choices ) else: raw_value = nf.get_local_value() if ( _mpad.debug_serial ): print ( "Received %s for '%s'" % \ ( str(raw_value), nf.name ) ) value = nf.offset + nf.scale * raw_value value = str(value) widget.SetLabel(value) widget.SetSize(widget.GetBestSize()) #============================================================================= class MpadRightPanel(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 = MpadStatusPanel( self ) self.box.Add( self.status_panel, border=5, \ flag=(wx.TOP | wx.BOTTOM | wx.ALIGN_LEFT) ) # # Insert two separators. # self.sep1a = wx.StaticLine( self ) self.box.Add( self.sep1a, flag=(wx.ALIGN_LEFT | wx.EXPAND ) ) self.sep1b = wx.StaticLine( self ) self.box.Add( self.sep1b, flag=(wx.ALIGN_LEFT | wx.EXPAND ) ) # # Create the sequence type panel. # self.sequence_panel = MpadSequencePanel( self ) self.box.Add( self.sequence_panel, border=5, \ flag=(wx.TOP | wx.ALIGN_LEFT) ) # # Insert a separator. # self.sep2 = wx.StaticLine( self ) self.box.Add( self.sep2, border=5, \ flag=(wx.TOP | wx.ALIGN_LEFT | wx.EXPAND ) ) # # Create the Start button. # self.start_button = wx.Button( self, label="Start Sequence" ) self.Bind( wx.EVT_BUTTON, self.OnStartButton, self.start_button ) self.box.Add( self.start_button, border=5, \ flag=(wx.TOP | wx.ALIGN_CENTER)) # # Create the Stop button. # self.stop_button = wx.Button( self, label="Stop Sequence" ) self.Bind( wx.EVT_BUTTON, self.OnStopButton, self.stop_button ) self.box.Add( self.stop_button, border=5, \ flag=(wx.TOP | wx.ALIGN_CENTER)) # # Insert two separators. # self.sep3c = wx.StaticLine( self ) self.box.Add( self.sep3c, border=10, \ flag=(wx.TOP | wx.ALIGN_LEFT | wx.EXPAND ) ) self.sep3d = wx.StaticLine( self ) self.box.Add( self.sep3d, border=5, \ flag=(wx.BOTTOM | wx.ALIGN_LEFT | wx.EXPAND ) ) # # Create the dark current panel. # self.dark_current_panel = MpadDarkCurrentPanel( self ) self.box.Add( self.dark_current_panel, flag=wx.ALIGN_CENTER ) # # Insert two separators. # self.sep5a = wx.StaticLine( self ) self.box.Add( self.sep5a, border=10, \ flag=(wx.TOP | wx.ALIGN_LEFT | wx.EXPAND ) ) self.sep5b = wx.StaticLine( self ) self.box.Add( self.sep5b, border=5, \ flag=(wx.BOTTOM | wx.ALIGN_LEFT | wx.EXPAND ) ) # # Create the datafile panel. # self.datafile_panel = MpadDatafilePanel( self ) self.box.Add( self.datafile_panel, flag=wx.ALIGN_CENTER ) self.SetSizer( self.box ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def OnStartButton( self, event ): panel = self.sequence_panel.current_sequence_panel if ( panel == None ): raise AssertionError("current_sequence_panel is None!") # Invoke the command for this sequence panel. _mpad.is_busy = True panel.command( panel ) def OnStopButton( self, event ): _mpad.ad_record.stop() #------------------------------------------------------------------------------ class MpadStatusPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.grid = wx.GridBagSizer() status_width = 40 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.lfn_label = wx.StaticText( self, -1, "Frame Number: " ) self.grid.Add( self.lfn_label, pos=(0,0) ) lfn_name = "%s.last_frame_number" % ( _mpad.remote_ad_name ) self.lfn_value = MpWx.Value( self, \ _mpad.server_record, lfn_name, \ size=(status_width,-1) ) self.lfn_value.SetForegroundColour( "blue" ) self.grid.Add( self.lfn_value, pos=(0,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.tnf_label = wx.StaticText( self, -1, "Total # Frames: " ) self.grid.Add( self.tnf_label, pos=(1,0) ) tnf_name = "%s.total_num_frames" % ( _mpad.remote_ad_name ) self.tnf_value = MpWx.Value( self, \ _mpad.server_record, tnf_name, \ function = mpad_total_num_frames_callback_function, \ args = self.lfn_value.nf, size=(status_width,-1) ) self.tnf_value.SetForegroundColour( "blue" ) self.grid.Add( self.tnf_value, pos=(1,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # This widget must be created "out of order" so that # the self.status_text attribute already exists the # first time that mpad_status_callback_function() # is invoked. # self.status_text = wx.StaticText( self, -1, "Idle", \ size=(200,-1) ) self.status_text.SetForegroundColour( "limegreen" ) self.grid.Add( self.status_text, pos=(2,2), border=20, \ flag=wx.LEFT ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.status_label = wx.StaticText( self, -1, "Status:" ) self.grid.Add( self.status_label, pos=(2,0) ) status_name = "%s.status" % ( _mpad.remote_ad_name ) self.status_value = MpWx.Value( self, \ _mpad.server_record, status_name, \ function = mpad_status_callback_function, \ size=(status_width,-1) ) self.status_value.SetForegroundColour( "blue" ) self.grid.Add( self.status_value, pos=(2,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.Bind( wx.EVT_IDLE, self.OnIdle ) self.SetSizer( self.grid ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - initial_frame_number = self.lfn_value.nf.get_local_value() if ( initial_frame_number >= 0 ): _mpad.fetch_image_frame = True def OnIdle( self, event ): last_frame_number_nf = self.lfn_value.nf frame_number = last_frame_number_nf.get_local_value() if ( _mpad.fetch_image_frame and ( frame_number >= 0 ) ): _mpad.fetch_image_frame = False print ( "*** Getting frame %d from server ***" \ % frame_number ) get_frame_from_server( Mp.MXFT_AD_IMAGE_FRAME, \ frame_number ) #---- def mpad_total_num_frames_callback_function( nf, widget, args, value ): _mpad.fetch_image_frame = True MpWx._Value_update( nf, widget, args, value ) return #---- def mpad_status_callback_function( nf, widget, args, value ): MpWx._Value_update( nf, widget, args, value ) if ( value == 0 ): text = "Idle" color = "limegreen" elif ( value & 0x1000 ): text = "Exposure time conflict" color = "red" elif ( value & 0x800 ): text = "Disk full" color = "red" elif ( value & 0x400 ): text = "Permission denied" color = "red" elif ( value & 0x200 ): text = "File I/O error" color = "red" elif ( value & 0x100 ): text = "Buffer overrun" elif ( value & 4 ): text = "Correction measurement" color = "orange" elif ( value & 2 ): text = "Correcting" color = "red" elif ( value & 1 ): text = "Acquiring" color = "red" elif ( value & 0x80000000 ): text = "Unspecified error" color = "purple" else: text = "Unknown" color = "purple" status_text = widget.parent.status_text status_text.SetLabel( text ) status_text.SetForegroundColour( color ) # # At the end of the status callback, we check to see if any saved # correction flags are stored. If so, then check to see if the # Mp.MXSF_AD_CORRECTION_MEASUREMENT_IN_PROGRESS bit is set. If # that bit is _not_ set, then we assume that a correction measurement # has just completed and we restore the previously saved value # of the correction flags. # if ( _mpad.saved_correction_flags != 0 ): if ( (value & Mp.MXSF_AD_CORRECTION_MEASUREMENT_IN_PROGRESS) \ == 0 ): restore_timer = MpadRestoreCorrFlagsTimer( widget ) restore_timer.Start(1) #------------------------------------------------------------------------------ class MpadRestoreCorrFlagsTimer(wx.Timer): def __init__( self, parent ): wx.Timer.__init__( self, parent, -1 ) self.parent = parent parent.Bind( wx.EVT_TIMER, self.OnCallback, self ) def OnCallback( self, event ): _mpad.ad_record.set_correction_flags( _mpad.saved_correction_flags ) _mpad.saved_correction_flags = 0 self.Stop() self.Destroy() #------------------------------------------------------------------------------ class MpadContrastPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.title = wx.StaticText( self, -1, "Contrast: " ) self.grid.Add( self.title, pos=(0,0), \ flag=wx.ALIGN_CENTER_VERTICAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.black_label = wx.StaticText( self, -1, "Black: " ) self.grid.Add( self.black_label, pos=(0,1), \ flag=wx.ALIGN_CENTER_VERTICAL ) self.black_value = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.black_value.SetValue("0") self.grid.Add( self.black_value, pos=(0,2), \ flag=wx.ALIGN_CENTER_VERTICAL ) self.white_label = wx.StaticText( self, -1, " White: " ) self.grid.Add( self.white_label, pos=(0,3), \ flag=wx.ALIGN_CENTER_VERTICAL ) self.white_value = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.white_value.SetValue("65535") self.grid.Add( self.white_value, pos=(0,4), \ flag=wx.ALIGN_CENTER_VERTICAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.change_button = wx.Button( self, label="Change Contrast" ) self.grid.Add( self.change_button, pos=(0,5), border=10, \ flag=( wx.LEFT | wx.ALIGN_CENTER_VERTICAL ) ) self.Bind( wx.EVT_BUTTON, self.OnChangeButton, \ self.change_button ) self.autoscale_button = wx.Button( self, label="Autoscale" ) self.grid.Add( self.autoscale_button, pos=(0,6), border=10, \ flag=( wx.LEFT | wx.ALIGN_CENTER_VERTICAL ) ) self.Bind( wx.EVT_BUTTON, self.OnAutoscaleButton, \ self.autoscale_button ) self.SetSizer( self.grid ) def OnChangeButton( self, event ): black_value = int( self.black_value.GetValue() ) white_value = int( self.white_value.GetValue() ) print ( \ "Changing contrast: black_value = %d, white_value = %d" \ % ( black_value, white_value ) ) panel = _mpad.frame.image_tab.mpad_image_panel.image_foo panel.SetGreyRampColormap( black_value, white_value ) panel.Display() def OnAutoscaleButton( self, event ): panel = _mpad.frame.image_tab.mpad_image_panel.image_foo ( mean, std_dev, min, max ) = panel.GetStatistics() black_value = round( mean - 2.0 * std_dev ) white_value = round( mean + 2.0 * std_dev ) black_value = int(black_value) white_value = int(white_value) if ( black_value < 0 ): black_value = 0 if ( white_value > 65535 ): white_value = 65535 panel.SetGreyRampColormap( black_value, white_value ) self.black_value.SetValue( str(black_value) ) self.white_value.SetValue( str(white_value) ) panel.Display() #------------------------------------------------------------------------------ class MpadDarkCurrentPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.grid = wx.GridBagSizer() self.SetSizer( self.grid ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.title = wx.StaticText( self, -1, "Dark Current" ) self.grid.Add( self.title, pos=(0,0), span=(1,2), border=5, \ flag=(wx.BOTTOM | wx.ALIGN_CENTER) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.num_label = wx.StaticText( self, -1, \ "Number of Measurements: " ) self.grid.Add( self.num_label, pos=(1,0), border=5, \ flag=(wx.LEFT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.num_ctrl = wx.TextCtrl( self ) self.grid.Add( self.num_ctrl, pos=(1,1), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.time_label = wx.StaticText( self, -1, "Measurement Time: ") self.grid.Add( self.time_label, pos=(2,0), border=5, \ flag=(wx.LEFT | wx.TOP | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.time_ctrl = wx.TextCtrl( self ) self.grid.Add( self.time_ctrl, pos=(2,1), border=5, \ flag=(wx.TOP | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.button_panel = wx.Panel( self ) self.grid.Add( self.button_panel, pos=(3,0), span=(1,2), \ border=10, flag=(wx.ALL | wx.ALIGN_CENTER) ) self.button_box = wx.BoxSizer( wx.HORIZONTAL ) self.button_panel.SetSizer( self.button_box ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.start_button = wx.Button( self.button_panel, \ label="Start Measurement" ) self.button_box.Add( self.start_button ) self.Bind( wx.EVT_BUTTON, self.OnStartButton, \ self.start_button ) self.cancel_button = wx.Button( self.button_panel, \ label="Cancel" ) self.button_box.Add( self.cancel_button ) self.Bind( wx.EVT_BUTTON, self.OnCancelButton, \ self.cancel_button ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.Fit() def OnCancelButton( self, event ): print ( "Cancel button pressed." ) _mpad.ad_record.stop() def OnStartButton( self, event ): print ( "Start button pressed." ) #--- _mpad.saved_correction_flags = \ _mpad.ad_record.get_correction_flags() print ( "saved_correction_flags =", \ _mpad.saved_correction_flags ) _mpad.ad_record.set_correction_flags( 0 ) #--- measurement_time_string = self.time_ctrl.GetValue() if ( measurement_time_string == "" ): return num_measurements_string = self.num_ctrl.GetValue() if ( num_measurements_string == "" ): return measurement_time = float( measurement_time_string ) num_measurements = int( num_measurements_string ) print ( \ "Starting dark current measurement for area detector '%s'." \ % _mpad.ad_record.name ) print ( \ "measurement time = %g seconds, number of measurements = %d" \ % ( measurement_time, num_measurements ) ) _mpad.ad_record.measure_dark_current_frame( \ measurement_time, num_measurements ) _mpad.correction_timer = MpadCorrectionTimer( self ) _mpad.correction_timer.Start(1000) #------------------------------------------------------------------------------ class MpadCorrectionTimer(wx.Timer): def __init__( self, parent ): wx.Timer.__init__( self, parent, -1 ) self.parent = parent parent.Bind( wx.EVT_TIMER, self.OnCallback, self ) def OnCallback( self, event ): ad_status = _mpad.ad_record.get_status() if ( ad_status != 0 ): return _mpad.ad_record.transfer_frame( Mp.MXFT_AD_DARK_CURRENT_FRAME, \ _mpad.image_frame ) mpad_image_panel = _mpad.frame.image_tab.mpad_image_panel mpad_image_panel.SetData( _mpad.image_frame ) mpad_image_panel.Display() self.Stop() self.Destroy() _mpad.correction_timer = None _mpad.fetch_image_frame = False #------------------------------------------------------------------------------ class MpadDatafilePanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.grid = wx.GridBagSizer() row = 0 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.title = wx.StaticText( self, -1, "Image Destination" ) self.grid.Add( self.title, pos=(row,0), span=(1,3), border=5, flag=(wx.BOTTOM | wx.ALIGN_CENTER) ) row = row + 1 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.directory_label = wx.StaticText( self, -1, "Directory:" ) self.grid.Add( self.directory_label, pos=(row,0), border=5, flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) directory_nf_name = \ "%s.datafile_directory" % _mpad.remote_ad_name self.spacer = wx.StaticText( self, -1, " " ) self.grid.Add( self.spacer, pos=(row,1) ) self.directory_value = MpadDatafileDirectory( self ) self.grid.Add( self.directory_value, pos=(row,2), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) row = row + 1 #- - - self.pattern_label = wx.StaticText( self, -1, "Pattern:" ) self.grid.Add( self.pattern_label, pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) pattern_nf_name = "%s.datafile_pattern" % _mpad.remote_ad_name self.pattern_value = MpWx.ValueEntry( self, _mpad.server_record, pattern_nf_name, size=(200,-1) ) self.grid.Add( self.pattern_value, pos=(row,2), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) row = row + 1 #- - - self.filename_label = \ wx.StaticText( self, -1, "Filename:" ) self.grid.Add( self.filename_label, pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) filename_nf_name = "%s.datafile_name" % _mpad.remote_ad_name self.filename_value = MpWx.Value( self, _mpad.server_record, filename_nf_name ) self.filename_value.SetForegroundColour( "blue" ) self.grid.Add( self.filename_value, pos=(row,2), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) row = row + 1 #- - - self.next_file_number_label = \ wx.StaticText( self, -1, "Last Datafile Number:" ) self.grid.Add( self.next_file_number_label, pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) next_file_number_nf_name = \ "%s.datafile_number" % _mpad.remote_ad_name self.next_file_number_value = MpWx.ValueEntry( self, _mpad.server_record, next_file_number_nf_name, size=(200,-1) ) self.grid.Add( self.next_file_number_value, pos=(row,2), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) row = row + 1 #- - - if 1: self.autoselect_number_label = \ wx.StaticText( self, -1, "Autoselect Number:" ) self.grid.Add( self.autoselect_number_label,pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) autoselect_number_nf_name = \ "%s.datafile_autoselect_number" % _mpad.remote_ad_name self.autoselect_number_value = MpWx.ValueEntry( self, _mpad.server_record, autoselect_number_nf_name, size=(30,-1) ) self.grid.Add( self.autoselect_number_value,pos=(row,2), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) row = row + 1 self.allow_overwrite_label = \ wx.StaticText( self, -1, "Allow Overwrite:" ) self.grid.Add( self.allow_overwrite_label, pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) allow_overwrite_nf_name = \ "%s.datafile_allow_overwrite" % _mpad.remote_ad_name self.allow_overwrite_value = MpWx.ValueEntry( self, _mpad.server_record, allow_overwrite_nf_name, size=(30,-1) ) self.grid.Add( self.allow_overwrite_value, pos=(row,2), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) #- - - self.SetSizer( self.grid ) #------------------------------------------------------------------------------ class MpadDatafileDirectory(wx.lib.filebrowsebutton.DirBrowseButton): def __init__( self, parent ): wx.lib.filebrowsebutton.DirBrowseButton.__init__( self, parent, labelText="", size=(300, -1) ) self.parent = parent field_name = "%s.datafile_directory" % ( _mpad.remote_ad_name ) self.nf = Mp.Net( _mpad.server_record, field_name ) # # Disable the widget if the network field is read only. # read_only = self.nf.get_attribute( Mp.MXNA_READ_ONLY ) if ( read_only ): self.Enable(False) # # See if remote and local directory variables have been # defined. These are used if the detector's data file # directory has been NFS or SMB exported to the client. # try: self.remote_dir_record = \ _mpad.mx_database.get_record( "mx_remote_dir" ) self.local_dir_record = \ _mpad.mx_database.get_record( "mx_local_dir" ) except: self.remote_dir_record = None self.local_dir_record = None # # Fetch the initial value of the field. # function = mpad_datafile_directory_callback self.nf.get_with_callback( function, None, self ) # Set up a value changed callback for the field. self.callback = self.nf.add_callback( Mp.MXCBT_VALUE_CHANGED, function, None, self ) # # Override the createTextControl method, so that it creates the # TextCtrl widget with style wx.TE_PROCESS_ENTER, which is necessary # for wx.EVT_TEXT_ENTER events to work. We must override this # method since it does not appear to be possible to change the # TextCtrl style after the widget has been created. # def createTextControl( self ): text_control = wx.TextCtrl( self, style=wx.TE_PROCESS_ENTER ) text_control.SetToolTipString( self.toolTip ) text_control.Bind(wx.EVT_TEXT_ENTER, self.OnEnter ) return text_control def OnEnter( self, event ): new_path = self.GetValue() if ( self.remote_dir_record != None ): new_path = mpad_transform_path( self, new_path, True ) self.nf.put( new_path ) def OnBrowse( self, ev = None ): current_path = self.GetValue() if ( current_path == "" ): current_path = "." dialog = wx.DirDialog( self, message = "", defaultPath = current_path, style = wx.TAB_TRAVERSAL ) if ( dialog.ShowModal() == wx.ID_OK ): new_path = dialog.GetPath() if ( self.remote_dir_record != None ): new_path = \ mpad_transform_path( self, new_path, True ) self.nf.put( new_path ) self.SetValue( new_path ) dialog.Destroy() #--- def mpad_datafile_directory_callback( callback, args ): nf = callback.nf value = nf.get_local_value() value = str( value ) widget = callback.object if ( widget.remote_dir_record != None ): value = mpad_transform_path( widget, value, False ) widget.SetValue( value ) widget.SetSize( widget.GetBestSize() ) #--- def mpad_transform_path( dir_widget, old_filename, local_to_remote ): if ( local_to_remote ): old_prefix = dir_widget.local_dir_record.read() new_prefix = dir_widget.remote_dir_record.read() else: old_prefix = dir_widget.remote_dir_record.read() new_prefix = dir_widget.local_dir_record.read() new_filename = \ Mp.change_filename_prefix( old_filename, old_prefix, new_prefix ) print ( "mpad_transform_path: old_prefix = '%s', new_prefix = '%s'" \ % ( old_prefix, new_prefix ) ) print ("mpad_transform_path: old_filename = '%s', new_filename = '%s'" \ % ( old_filename, new_filename ) ) return new_filename #------------------------------------------------------------------------------ class MpadSequencePanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.box = wx.BoxSizer( wx.VERTICAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.sequence_type_list = [] self.sequence_panel_list = [] self.sequence_type_list.append('One-Shot') self.sequence_panel_list.append( \ MpadOneShotPanel( self, mpad_start_one_shot ) ) self.sequence_type_list.append('Continuous') self.sequence_panel_list.append( \ MpadContinuousPanel( self, mpad_start_continuous ) ) self.sequence_type_list.append('Multiframe') self.sequence_panel_list.append( \ MpadMultiframePanel( self, mpad_start_multiframe ) ) self.sequence_type_list.append('Circular Multiframe') self.sequence_panel_list.append( \ MpadCircularMultiframePanel( self, mpad_start_circular_multiframe ) ) self.sequence_type_list.append('Strobe') self.sequence_panel_list.append( \ MpadStrobePanel( self, mpad_start_strobe ) ) self.sequence_type_list.append('Duration') self.sequence_panel_list.append( \ MpadDurationPanel( self, mpad_start_duration ) ) self.sequence_type_list.append('Gated') self.sequence_panel_list.append( \ MpadGatedPanel( self, mpad_start_gated ) ) self.sequence_type_list.append('Geometrical') self.sequence_panel_list.append( \ MpadGeometricalPanel( self, mpad_start_geometrical ) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.sequence_type_panel = MpadSequenceTypePanel( self ) self.box.Add( self.sequence_type_panel, border=10, \ flag = wx.BOTTOM ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Load the default sequence panel. self.box.Add( self.sequence_panel_list[0] ) self.current_sequence_panel = self.sequence_panel_list[0] self.SetSizer( self.box ) #------------------------------------------------------------------------------ class MpadSequenceTypePanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.box = wx.BoxSizer( wx.HORIZONTAL ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.label = wx.StaticText( self, -1, "Sequence Type: " ) self.box.Add( self.label, flag=(wx.LEFT | wx.ALIGN_CENTER) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.selector = wx.Choice( self, -1, \ choices=parent.sequence_type_list ) self.selector.SetSelection(0) self.box.Add( self.selector, 1, wx.LEFT ) self.Bind( wx.EVT_CHOICE, self.OnChoice, self.selector ) self.SetSizer( self.box ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def OnChoice( self, event ): selection = self.selector.GetSelection() parent = self.parent sequence_type = parent.sequence_type_list[selection] sequence_panel = parent.sequence_panel_list[selection] if ( parent.current_sequence_panel != None ): parent.box.Detach( parent.current_sequence_panel ) parent.current_sequence_panel.Show(False) parent.current_sequence_panel = None parent.box.Add( sequence_panel ) parent.current_sequence_panel = sequence_panel parent.current_sequence_panel.Show(True) # Resize the sequence window and everything around it. parent.current_sequence_panel.Layout() parent.Layout() if True: # This way is faster. _mpad.frame.image_tab.right_panel.sequence_panel.Layout() _mpad.frame.image_tab.right_panel.Layout() _mpad.frame.image_tab.Layout() _mpad.frame.Layout() else: # The following is more general, but noticeably slower. w = self while True: w = w.GetParent() if ( w == None ): break w.Layout() _mpad.frame.Fit() # Force a redraw of the entire GUI. _mpad.frame.Refresh() _mpad.frame.Update() #------------------------------------------------------------------------------ class MpadOneShotPanel(wx.Panel): def __init__( self, parent, command ): wx.Panel.__init__( self, parent ) self.parent = parent self.command = command self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.exposure_time_label = \ wx.StaticText( self, -1, "Exposure Time: " ) self.grid.Add( self.exposure_time_label, pos=(0,0), \ flag=wx.ALIGN_CENTER ) self.exposure_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.exposure_time_ctrl, pos=(0,1), \ border=5, flag=wx.RIGHT ) self.exposure_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.exposure_time_units, pos=(0,2), \ flag=wx.ALIGN_CENTER ) self.SetSizer( self.grid ) def mpad_start_one_shot( panel ): value = panel.exposure_time_ctrl.GetValue() seconds = float(value) print ( "Starting one-shot exposure for %g seconds." % seconds ) _mpad.ad_record.set_one_shot_mode( seconds ) _mpad.ad_record.start() _mpad.is_busy = True #------------------------------------------------------------------------------ class MpadContinuousPanel(wx.Panel): def __init__( self, parent, command ): wx.Panel.__init__( self, parent ) self.parent = parent self.command = command self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.exposure_time_label = \ wx.StaticText( self, -1, "Exposure Time Per Frame: " ) self.grid.Add( self.exposure_time_label, pos=(0,0), \ flag=wx.ALIGN_CENTER ) self.exposure_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.exposure_time_ctrl, pos=(0,1), \ border=5, flag=wx.RIGHT ) self.exposure_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.exposure_time_units, pos=(0,2), \ flag=wx.ALIGN_CENTER ) self.SetSizer( self.grid ) def mpad_start_continuous( panel ): value = panel.exposure_time_ctrl.GetValue() seconds = float(value) print ( \ "Starting continuous exposure for %g seconds per frame." % seconds ) _mpad.ad_record.set_continuous_mode( seconds ) _mpad.ad_record.start() _mpad.is_busy = True #------------------------------------------------------------------------------ class MpadMultiframePanel(wx.Panel): def __init__( self, parent, command ): wx.Panel.__init__( self, parent ) self.parent = parent self.command = command self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.num_frames_label = \ wx.StaticText( self, -1, "Number of Frames: " ) self.grid.Add( self.num_frames_label, pos=(0,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.num_frames_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.num_frames_ctrl, pos=(0,1), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.exposure_time_label = \ wx.StaticText( self, -1, "Exposure Time: " ) self.grid.Add( self.exposure_time_label, pos=(1,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.exposure_time_ctrl, pos=(1,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.exposure_time_units, pos=(1,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.frame_time_label = \ wx.StaticText( self, -1, "Frame Time: " ) self.grid.Add( self.frame_time_label, pos=(2,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.frame_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.frame_time_ctrl, pos=(2,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.frame_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.frame_time_units, pos=(2,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.SetSizer( self.grid ) def mpad_start_multiframe( panel ): num_frames = int( panel.num_frames_ctrl.GetValue() ) exposure_seconds = float( panel.exposure_time_ctrl.GetValue() ) frame_seconds = float( panel.frame_time_ctrl.GetValue() ) print ( \ "Starting multiframe exposure for %d frames, exposure time %g, frame time %g" \ % ( num_frames, exposure_seconds, frame_seconds ) ) _mpad.ad_record.set_multiframe_mode( num_frames, \ exposure_seconds, frame_seconds ) _mpad.ad_record.start() _mpad.is_busy = True #------------------------------------------------------------------------------ class MpadCircularMultiframePanel(wx.Panel): def __init__( self, parent, command ): wx.Panel.__init__( self, parent ) self.parent = parent self.command = command self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.num_frames_label = \ wx.StaticText( self, -1, "Number of Frames: " ) self.grid.Add( self.num_frames_label, pos=(0,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.num_frames_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.num_frames_ctrl, pos=(0,1), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.exposure_time_label = \ wx.StaticText( self, -1, "Exposure Time: " ) self.grid.Add( self.exposure_time_label, pos=(1,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.exposure_time_ctrl, pos=(1,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.exposure_time_units, pos=(1,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.frame_time_label = \ wx.StaticText( self, -1, "Frame Time: " ) self.grid.Add( self.frame_time_label, pos=(2,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.frame_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.frame_time_ctrl, pos=(2,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.frame_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.frame_time_units, pos=(2,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.SetSizer( self.grid ) def mpad_start_circular_multiframe( panel ): num_frames = int( panel.num_frames_ctrl.GetValue() ) exposure_seconds = float( panel.exposure_time_ctrl.GetValue() ) frame_seconds = float( panel.frame_time_ctrl.GetValue() ) print ( \ "Starting circular multiframe exposure for %d frames, exposure time %g, frame time %g" \ % ( num_frames, exposure_seconds, frame_seconds ) ) _mpad.ad_record.set_circular_multiframe_mode( num_frames, \ exposure_seconds, frame_seconds ) _mpad.ad_record.start() _mpad.is_busy = True #------------------------------------------------------------------------------ class MpadStrobePanel(wx.Panel): def __init__( self, parent, command ): wx.Panel.__init__( self, parent ) self.parent = parent self.command = command self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.num_frames_label = \ wx.StaticText( self, -1, "Number of Frames: " ) self.grid.Add( self.num_frames_label, pos=(0,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.num_frames_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.num_frames_ctrl, pos=(0,1), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.exposure_time_label = \ wx.StaticText( self, -1, "Exposure Time: " ) self.grid.Add( self.exposure_time_label, pos=(1,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.exposure_time_ctrl, pos=(1,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.exposure_time_units, pos=(1,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.SetSizer( self.grid ) def mpad_start_strobe( panel ): num_frames = int( panel.num_frames_ctrl.GetValue() ) exposure_seconds = float( panel.exposure_time_ctrl.GetValue() ) print ( \ "Starting strobe exposure for %d frames, exposure time %g second" \ % ( num_frames, exposure_seconds ) ) _mpad.ad_record.set_strobe_mode( num_frames, exposure_seconds ) _mpad.ad_record.start() _mpad.is_busy = True #------------------------------------------------------------------------------ class MpadDurationPanel(wx.Panel): def __init__( self, parent, command ): wx.Panel.__init__( self, parent ) self.parent = parent self.command = command self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.num_frames_label = \ wx.StaticText( self, -1, "Number of Frames: " ) self.grid.Add( self.num_frames_label, pos=(0,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.num_frames_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.num_frames_ctrl, pos=(0,1), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.SetSizer( self.grid ) def mpad_start_duration( panel ): num_frames = int( panel.num_frames_ctrl.GetValue() ) print ( "Starting duration exposure for %d frames" % num_frames ) _mpad.ad_record.set_duration_mode( num_frames ) _mpad.ad_record.start() _mpad.is_busy = True #------------------------------------------------------------------------------ class MpadGatedPanel(wx.Panel): def __init__( self, parent, command ): wx.Panel.__init__( self, parent ) self.parent = parent self.command = command self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.num_frames_label = \ wx.StaticText( self, -1, "Number of Frames: " ) self.grid.Add( self.num_frames_label, pos=(0,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.num_frames_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.num_frames_ctrl, pos=(0,1), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.SetSizer( self.grid ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.exposure_time_label = \ wx.StaticText( self, -1, "Exposure Time: " ) self.grid.Add( self.exposure_time_label, pos=(1,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.exposure_time_ctrl, pos=(1,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.exposure_time_units, pos=(1,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.gate_time_label = \ wx.StaticText( self, -1, "Gate Time: " ) self.grid.Add( self.gate_time_label, pos=(2,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.gate_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.gate_time_ctrl, pos=(2,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.gate_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.gate_time_units, pos=(2,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) def mpad_start_gated( panel ): num_frames = int( panel.num_frames_ctrl.GetValue() ) exposure_seconds = float( panel.exposure_time_ctrl.GetValue() ) gate_seconds = float( panel.gate_time_ctrl.GetValue() ) print ( "Starting duration exposure for %d frames" % num_frames ) _mpad.ad_record.set_gated_mode( num_frames, exposure_seconds, gate_seconds ) _mpad.ad_record.start() _mpad.is_busy = True #------------------------------------------------------------------------------ class MpadGeometricalPanel(wx.Panel): def __init__( self, parent, command ): wx.Panel.__init__( self, parent ) self.parent = parent self.command = command self.grid = wx.GridBagSizer() #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.num_frames_label = \ wx.StaticText( self, -1, "Number of Frames: " ) self.grid.Add( self.num_frames_label, pos=(0,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.num_frames_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.num_frames_ctrl, pos=(0,1), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.exposure_time_label = \ wx.StaticText( self, -1, "Exposure Time: " ) self.grid.Add( self.exposure_time_label, pos=(1,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.exposure_time_ctrl, pos=(1,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.exposure_time_units, pos=(1,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.gap_time_label = \ wx.StaticText( self, -1, "Gap Time: " ) self.grid.Add( self.gap_time_label, pos=(2,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.gap_time_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.gap_time_ctrl, pos=(2,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.gap_time_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.gap_time_units, pos=(2,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.exposure_multiplier_label = \ wx.StaticText( self, -1, "Exposure Multiplier: " ) self.grid.Add( self.exposure_multiplier_label, pos=(3,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.exposure_multiplier_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.exposure_multiplier_ctrl, \ pos=(3,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.gap_multiplier_label = \ wx.StaticText( self, -1, "Gap Multiplier: " ) self.grid.Add( self.gap_multiplier_label, pos=(4,0), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.gap_multiplier_ctrl = wx.TextCtrl( self, \ validator = MpadFloatValidator() ) self.grid.Add( self.gap_multiplier_ctrl, pos=(4,1), border=5, \ flag=(wx.RIGHT | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.gap_multiplier_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.gap_multiplier_units, pos=(4,2), \ flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) self.SetSizer( self.grid ) def mpad_start_geometrical( panel ): num_frames = int( panel.num_frames_ctrl.GetValue() ) exposure_seconds = float( panel.exposure_time_ctrl.GetValue() ) gap_seconds = float( panel.gap_time_ctrl.GetValue() ) exposure_multiplier = float( panel.exposure_multiplier_ctrl.GetValue() ) gap_multiplier = float( panel.gap_multiplier_ctrl.GetValue() ) print ( \ "Starting geometrical exposure for %d frames, exposure time %g, gap time %g, " \ "exposure multiplier %g, gap multiplier %g" \ % ( num_frames, exposure_seconds, gap_seconds, \ exposure_multiplier, gap_multiplier ) ) _mpad.ad_record.set_geometrical_mode( num_frames, \ exposure_seconds, gap_seconds, \ exposure_multiplier, gap_multiplier ) _mpad.ad_record.start() _mpad.is_busy = True #============================================================================= class MpadValueText(wx.TextCtrl): def __init__( self, parent, window_id, initial_text ): wx.TextCtrl.__init__( self, parent, \ id=window_id, value=initial_text, \ style=wx.TE_READONLY|wx.NO_BORDER ) self.parent = parent self.SetBackgroundColour( self.parent.GetBackgroundColour() ) def SetValue( self, value ): string_value = str(value) wx.TextCtrl.SetValue( self, string_value ) # wx.TextCtrl.SetForegroundColour( self, wx.Colour(255,0,0) ) #------------------------------------------------------------------------ def rebin( a, newshape ): ''' Rebin an array to a new shape. newshape must be a factor of shape. This came from http://scipy.org/Cookbook/Rebinning ''' assert len(a.shape) == len(newshape) slices = [ slice(None,None, old/new) \ for old,new in zip(a.shape,newshape) ] return a[slices] #----------------------------------------------------------------------------- def get_server_frame_type( selection ): if ( selection == 0 ): server_frame_type = Mp.MXFT_AD_IMAGE_FRAME elif ( selection == 1 ): server_frame_type = Mp.MXFT_AD_MASK_FRAME elif ( selection == 2 ): server_frame_type = Mp.MXFT_AD_BIAS_FRAME elif ( selection == 3 ): server_frame_type = Mp.MXFT_AD_DARK_CURRENT_FRAME elif ( selection == 4 ): server_frame_type = Mp.MXFT_AD_FLAT_FIELD_FRAME else: msg = "Illegal server frame type %d requested." % selection raise Mp.CorruptDataStructureError( msg ) return server_frame_type #------------------------------------------------------------------------ def get_frame_from_server( frame_type, frame_number ): start_time = time.clock() # print ( "get_frame_from_server() invoked." ) # print ( "frame_type =", frame_type, " frame_number =", frame_number ) if ( frame_type == Mp.MXFT_AD_IMAGE_FRAME ): frame_name = 'image' elif ( frame_type == Mp.MXFT_AD_MASK_FRAME ): frame_name = 'mask' elif ( frame_type == Mp.MXFT_AD_BIAS_FRAME ): frame_name = 'bias' elif ( frame_type == Mp.MXFT_AD_DARK_CURRENT_FRAME ): frame_name = 'dark current' elif ( frame_type == Mp.MXFT_AD_FLAT_FIELD_FRAME ): frame_name = 'flat field' else: msg = "Unsupported frame type %x requested." % frame_type raise Mp.IllegalArgumentError( msg ) print ( "Reading %s frame, frame number %d" \ % ( frame_name, frame_number ) ) ad = _mpad.ad_record if ( frame_type == Mp.MXFT_AD_IMAGE_FRAME ): ad.setup_frame( _mpad.image_frame ) ad.readout_frame( frame_number ) ad.correct_frame() ad.transfer_frame( frame_type, _mpad.image_frame ) else: ad.transfer_frame( frame_type, _mpad.image_frame ) print ( "Frame read." ) mpad_image_panel = _mpad.frame.image_tab.mpad_image_panel frame_read_end_time = time.clock() mpad_image_panel.SetData( _mpad.image_frame ) convert_end_time = time.clock() mpad_image_panel.Display() display_end_time = time.clock() # print ( "frame read time = %f sec" % (frame_read_end_time - start_time) ) # print ( "convert time = %f sec" % (convert_end_time - frame_read_end_time) ) # print ( "display time = %f sec" % (display_end_time - convert_end_time) ) #=============================================================================