#! /usr/bin/env mpscript # import wxversion wxversion.ensureMinimal("2.8") import numpy import scipy.ndimage.filters import wx import wx.lib.filebrowsebutton import MpNum import MpWx import time import datetime try: import Image except: from PIL import Image # # Have we been requested to start a C debugger? # try: test = os.environ["DBDET_DEBUGGER"] Mp.c_wait_for_debugger() except: pass # # Create an object to hold attributes used by Dbdet. # class _Dbdet: pass _dbdet = _Dbdet() _dbdet.mxdir = mxdir _dbdet.callback_list = [] _dbdet.gui_ready = False _dbdet.fetch_image_frame = False _dbdet.saved_inhibit_autosave = False # Do we want a Python command entry window? _dbdet.debug_window = True # Do we want to display a log of the serial communication with the camera head? _dbdet.debug_serial = True # # Are we running a test version of Dbdet? # try: test = os.environ["DBDETTEST"] test = int(test) if ( test == 0 ): _dbdet.test = False else: _dbdet.test = True except: _dbdet.test = False if ( _dbdet.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 _dbdet.lib_dir = lib_dir _dbdet.etc_dir = etc_dir sys.path.append( lib_dir ) #--- import WxtImage #-------------------------------------------------------------------------- class DbdetApp(wx.App): def OnInit( self ): # # _dbdet.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. # _dbdet.is_busy = False self.frame = DbdetMainFrame() self.frame.Show() self.SetTopWindow( self.frame ) self.timer = DbdetTimer( self ) _dbdet.timer = self.timer # self.timer.Start( 100 ) self.timer.Start( 10 ) return True #-------------------------------------------------------------------------- def main( record_list, args ): _dbdet.record_list = record_list _dbdet.record_list.set_program_name('dbdet') # _dbdet.record_list.set_network_debug(True) # # Find the area detector record. # if ( len(args) > 0 ): ad_name = args[0] _dbdet.ad_record = _dbdet.record_list.get_record( ad_name ) # # Verify that the record we found is an area detector record. # mx_class = _dbdet.ad_record.get_field("mx_class") mx_type = _dbdet.ad_record.get_field("mx_type") if ( mx_class != "area_detector" ): msg = "Record '%s' is not an 'area_detector' record." \ " Instead, it is of type '%s'." \ % ( _dbdet.ad_record.name, mx_type ) raise Mp.Type_Mismatch_Error, msg else: # Find the first area detector record in the MX database. list_head = _dbdet.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 == "area_detector" ): _dbdet.ad_record = current_record print "Using area detector record '%s'" \ % _dbdet.ad_record.name break current_record = current_record.get_next_record() try: _dbdet.ad_record except NameError: msg = \ "The MX database does not contain an area detector record." raise Mp.Not_Found_Error, msg #------------------------------------------------------------------- # # What type of area detector record is this? # _dbdet.mx_type = _dbdet.ad_record.get_field("mx_type") # # If this is a network area detector record, find out what type # of record is being used by the server. # if ( _dbdet.mx_type != "network_area_detector" ): _dbdet.server_record = None _dbdet.remote_ad_name = None _dbdet.remote_mx_type = None _dbdet.inhibit_autosave_nf = None else: server_record_name = _dbdet.ad_record.get_field("server_record") _dbdet.server_record = \ _dbdet.record_list.get_record( server_record_name ) _dbdet.remote_ad_name = \ _dbdet.ad_record.get_field("remote_record_name") mx_type_nf_name = "%s.mx_type" % ( _dbdet.remote_ad_name ) mx_type_nf = Mp.Net( _dbdet.server_record, mx_type_nf_name ) _dbdet.remote_mx_type = mx_type_nf.get() #--- inhibit_autosave_nf_name = "%s.inhibit_autosave" \ % ( _dbdet.remote_ad_name ) if 0: _dbdet.inhibit_autosave_nf = Mp.Net( \ _dbdet.server_record, inhibit_autosave_nf_name ) else: _dbdet.inhibit_autosave_nf = None # Tell the server's area detector record to use RAW_GREY16 # format for its output datafiles. save_format_name_string = "%s.datafile_save_format_name" \ % ( _dbdet.remote_ad_name ) save_format_name_nf = Mp.Net( _dbdet.server_record, \ save_format_name_string ) save_format_name_nf.put( "RAW_GREY16" ) #------------ print "_dbdet.remote_mx_type =", _dbdet.remote_mx_type # #------------------------------------------------------------------- # # Initialize some parameters. # _dbdet.number_of_frames = 0 _dbdet.detector_status = 0 _dbdet.smooth_images = False _dbdet.collect_moving_average = False _dbdet.moving_average_list = [] _dbdet.acquire_dark_current_frame = False _dbdet.no_status_change_since_start = False # # Create the ImageFrame object that will be used to contain frames # read from the area detector. # maximum_framesize = _dbdet.ad_record.get_maximum_framesize() bytes_per_pixel = _dbdet.ad_record.get_bytes_per_pixel() _dbdet.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 = MpNum.ImageFrame( maximum_framesize, \ _dbdet.ad_record.get_image_format(), \ Mp.native_byteorder(), \ bytes_per_pixel, \ 0, \ image_length ) _dbdet.image_frame = image_frame _dbdet.ad_record.setup_frame( _dbdet.image_frame ) # # Create the WxPython GUI. # app = DbdetApp(redirect=False) _dbdet.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" ) load_site_script = True except: pass if ( load_site_script ): mx_site_name = mx_site.get_field( "value" ) mx_site_script = \ os.path.join( _dbdet.etc_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 DbdetMainFrame class is used to implement the top level window of Dbdet. # # #---------------------------------------------------------------------------- # class DbdetMainFrame(wx.Frame): def __init__( self ): wx.Frame.__init__( self, None, \ title="RDI Cmos Prototype" ) _dbdet.frame = self # # Create a panel to contain the notebook. # self.tab_panel = wx.Panel( self ) # # Create the tabbed notebook. # self.tab_notebook = DbdetNotebook( self.tab_panel ) # # Create and add the Image tab. # self.image_tab = DbdetImageTab( self.tab_notebook ) self.tab_notebook.AddPage( self.image_tab, "Image" ) # # Create and populate a menu bar. # self.menubar = DbdetMenuBar( 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 "DbdetMainFrame: OnSize(): size =", self.GetSize() event.Skip() #----------------------------------------------------------------------------- class DbdetNotebook(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 "DbdetNotebook: OnSize(): size = ", self.GetSize() event.Skip() #----------------------------------------------------------------------------- class DbdetMenuBar(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 = _dbdet.ad_record.get_field("mx_type") if ( ad_record_type == "network_area_detector" ): server_record_name = \ _dbdet.ad_record.get_field("server_record") server_record = \ _dbdet.record_list.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" ) 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.OnLoadServer, save_server_item ) exit_item = self.file_menu.Append( -1, "Exit" ) parent.Bind( wx.EVT_MENU, self.OnExit, exit_item ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Add the Help menu. # self.help_menu = wx.Menu() self.Append( self.help_menu, "Help" ) about_item = self.help_menu.Append( -1, "About Dbdet" ) parent.Bind( wx.EVT_MENU, self.OnAbout, about_item ) if ( _dbdet.debug_window ): debug_window_item = self.help_menu.Append( -1, \ "Debug Window" ) parent.Bind( wx.EVT_MENU, self.OnDebugWindow, \ debug_window_item ) def OnExit( self, event ): _dbdet.frame.Close( True ) def OnAbout( self, event ): dialog = DbdetAboutBox() dialog.ShowModal() dialog.Destroy() def OnLoadServer( self, event ): dialog = DbdetLoadSaveServerDialog( 'load' ) dialog.ShowModal() dialog.Destroy() def OnSaveServer( self, event ): dialog = DbdetLoadSaveServerDialog( 'save' ) dialog.ShowModal() dialog.Destroy() def OnDebugWindow( self, event ): dialog = DbdetDebugDialog() dialog.Show() #----------------------------------------------------------------------------- class DbdetLoadSaveServerDialog(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' ] 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 ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 = DbdetLoadSaveButtonPanel( 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 DbdetLoadSaveButtonPanel(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 _dbdet.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 _dbdet.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 DbdetDebugDialog(wx.Dialog): def __init__( self ): wx.Dialog.__init__( self, None, -1, "Dbdet 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 DbdetAboutBox(wx.Dialog): def __init__( self ): wx.Dialog.__init__( self, None, -1, "About Dbdet" ) 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-2009 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.description = wx.StaticText( self, -1, \ "Dbdet is a joint project of Aviex LLC\n" "and Illinois Institute of Technology" ) self.box.Add( self.description, border=10, \ flag=(wx.ALL | 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 DbdetImageTab(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.wxt_panel = DbdetWxtImagePanel( self ) self.image_tab_sizer.Add( self.wxt_panel, 1, \ border=10, flag=wx.EXPAND ) # # Create the right hand panel. # self.right_panel = DbdetRightPanel( 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 "DbdetImageTab: OnSize(): size =", self.GetSize() event.Skip() #============================================================================= class DbdetRightPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.box = wx.BoxSizer( wx.VERTICAL ) self.SetSizer( self.box ) # # Create the status panel. # self.status_panel = DbdetStatusPanel( self ) self.box.Add( self.status_panel, border=5, \ flag=(wx.TOP | wx.BOTTOM | wx.ALIGN_LEFT) ) # # Insert two separators. # self.sep0a = wx.StaticLine( self ) self.box.Add( self.sep0a, flag=(wx.ALIGN_LEFT | wx.EXPAND ) ) self.sep0b = wx.StaticLine( self ) self.box.Add( self.sep0b, flag=(wx.ALIGN_LEFT | wx.EXPAND ) ) # # Create the Start button. # self.start_button = wx.Button( self, label="Start" ) 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" ) 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.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 panel. # self.sequence_panel = DbdetSequencePanel( self ) self.box.Add( self.sequence_panel, border=5, \ flag=(wx.TOP | wx.ALIGN_LEFT) ) # # Insert two separators. # self.sep3a = wx.StaticLine( self ) self.box.Add( self.sep3a, border=10, \ flag=(wx.TOP | wx.ALIGN_LEFT | wx.EXPAND ) ) self.sep3b = wx.StaticLine( self ) self.box.Add( self.sep3b, border=5, \ flag=(wx.BOTTOM | wx.ALIGN_LEFT | wx.EXPAND ) ) # # Create the save file panel. # self.save_file_panel = DbdetSaveFilePanel( self ) self.box.Add( self.save_file_panel, border=5, \ flag=(wx.TOP | wx.ALIGN_CENTER) ) # # Insert two separators. # self.sep4a = wx.StaticLine( self ) self.box.Add( self.sep4a, border=10, \ flag=(wx.TOP | wx.ALIGN_LEFT | wx.EXPAND ) ) self.sep4b = wx.StaticLine( self ) self.box.Add( self.sep4b, border=5, \ flag=(wx.BOTTOM | wx.ALIGN_LEFT | wx.EXPAND ) ) # # Create the options panel. # self.options_panel = DbdetOptionsPanel( self ) self.box.Add( self.options_panel, border=5, \ flag=(wx.TOP | wx.ALIGN_LEFT) ) # # 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 = DbdetDatafilePanel( self ) self.box.Add( self.datafile_panel, border=5, \ flag=(wx.TOP | wx.ALIGN_LEFT) ) #------------------------------------ update_next_filename_widget( self ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def OnStartButton( self, event ): time_per_frame_ctrl = self.sequence_panel.time_per_frame_ctrl time_per_frame_string = time_per_frame_ctrl.GetValue() if ( time_per_frame_string == "" ): time_per_frame = 1 time_per_frame_ctrl.SetValue( "1" ) else: time_per_frame = float( time_per_frame_string ) if ( time_per_frame < 0 ): time_per_frame = 1 # Do we skip the first frame of a sequence? if 0: skip_first_frame_cb = \ self.options_panel.skip_first_frame_cb skip_first_frame = skip_first_frame_cb.IsChecked() else: skip_first_frame = False # Get the number of one-shot frames to acquire. number_of_frames_ctrl = \ self.sequence_panel.number_of_frames_ctrl number_of_frames_string = number_of_frames_ctrl.GetValue() if ( number_of_frames_string == "" ): number_of_frames = 1 number_of_frames_ctrl.SetValue( "1" ) else: number_of_frames = int( number_of_frames_string ) if ( number_of_frames < 1 ): number_of_frames = 1 if ( skip_first_frame ): do_skip_first_frame( time_per_frame ) ts_print( "Starting main sequence." ) if ( _dbdet.acquire_dark_current_frame ): # Start a dark current measurement. _dbdet.number_of_frames = 0 _dbdet.ad_record.measure_dark_current_frame( time_per_frame, number_of_frames ) _dbdet.is_busy = True else: # Configure a one-shot sequence. _dbdet.ad_record.set_one_shot_mode( time_per_frame ) _dbdet.number_of_frames = number_of_frames # Start the one-shot sequence. ts_print( "DbdetRightPanel: About to start()." ) _dbdet.ad_record.start() _dbdet.is_busy = True _dbdet.no_status_change_since_start = True _dbdet.last_start_time = time.time() def OnStopButton( self, event ): print "OnStopButton() invoked" _dbdet.ad_record.stop() _dbdet.is_busy = False _dbdet.number_of_frames = 0 _dbdet.no_status_change_since_start = False #------------------------------------------------------------------------------ def do_skip_first_frame( time_per_frame ): ts_print( "do_skip_first_frame() invoked." ) if ( _dbdet.inhibit_autosave_nf != None ): _dbdet.saved_inhibit_autosave = _dbdet.inhibit_autosave_nf.get() _dbdet.inhibit_autosave_nf.put( True ) # # Setup and start a throwaway frame. # if ( time_per_frame < 1.0 ): skip_time = time_per_frame else: skip_time = 1.0 _dbdet.ad_record.set_one_shot_mode( skip_time ) _dbdet.number_of_frames = 0 _dbdet.detector_status = 1 _dbdet.ad_record.start() _dbdet.is_busy = True _dbdet.no_status_change_since_start = True _dbdet.last_start_time = time.time() # # Wait for the frame to complete, while allowing WxPython events. # while True: wx.Yield() if ( _dbdet.detector_status == 0 ): break time.sleep(0.1) # # Discard the frame. # discard_frame( 0 ) #---- if ( _dbdet.inhibit_autosave_nf != None ): _dbdet.inhibit_autosave_nf.put( _dbdet.saved_inhibit_autosave ) ts_print( "do_skip_first_frame() complete." ) #------------------------------------------------------------------------------ class DbdetStatusPanel(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" % ( _dbdet.remote_ad_name ) self.lfn_value = MpWx.Value( self, \ _dbdet.server_record, lfn_name, \ size=(status_width,-1) ) self.lfn_value.SetForegroundColour( "blue" ) self.grid.Add( self.lfn_value, pos=(0,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # The next_filename_text widget must be created "out of order" # so that the self.next_filename_text attribute already exists # the first time that dbdet_total_num_frames_callback_function # is invoked. self.next_filename_label = wx.StaticText( self, -1, \ "Next Filename: " ) self.grid.Add( self.next_filename_label, pos=(4,0) ) self.next_filename_text = wx.StaticText( self, -1, "--------", \ size=(200,-1) ) self.next_filename_text.SetForegroundColour( "blue" ) self.grid.Add( self.next_filename_text, pos=(4,1), span=(1,2), \ border=20, flag=wx.LEFT ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.tnf_label = wx.StaticText( self, -1, "Total # Frames: " ) self.grid.Add( self.tnf_label, pos=(1,0) ) tnf_name = "%s.total_num_frames" % ( _dbdet.remote_ad_name ) self.tnf_value = MpWx.Value( self, \ _dbdet.server_record, tnf_name, \ function = dbdet_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 dbdet_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" % ( _dbdet.remote_ad_name ) self.status_value = MpWx.Value( self, \ _dbdet.server_record, status_name, \ function = dbdet_status_callback_function, \ size=(status_width,-1) ) self.status_value.SetForegroundColour( "blue" ) self.grid.Add( self.status_value, pos=(2,1) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Insert a blank space between the Status line and # the Next Filename line # self.spacer = wx.StaticText( self, -1, " " ) self.grid.Add( self.spacer, pos=(3,0) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 ): _dbdet.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 ( _dbdet.fetch_image_frame and ( frame_number >= 0 ) ): _dbdet.fetch_image_frame = False # ts_print( "*** Getting frame %d from server ***", \ # frame_number ) get_frame_from_server_and_rebin( Mp.MXFT_AD_IMAGE_FRAME, frame_number ) #---- def dbdet_update_next_filename_callback_function( nf, widget, args, value ): MpWx._ValueEntry_update( nf, widget, args, value ) datafile_panel = widget.GetParent() right_panel = datafile_panel.GetParent() update_next_filename_widget( right_panel ) #---- def update_next_filename_widget( right_panel ): print "### right_panel =", right_panel try: datafile_panel = right_panel.datafile_panel except: print "right_panel.datafile_panel does not yet exist." return print "### datafile_panel =", datafile_panel datafile_directory = datafile_panel.directory_value print "datafile_directory =", datafile_directory pattern_value_widget = datafile_panel.pattern_value pattern_value = pattern_value_widget.GetValue() print "pattern_value =", pattern_value last_datafile_number_widget = datafile_panel.last_file_number_value last_datafile_number = last_datafile_number_widget.GetValue() try: last_datafile_number = int(last_datafile_number) except: print "Invalid last_datafile_number = '%s'" \ % last_datafile_number return print "last_datafile_number =", last_datafile_number #---- number_sign_index = pattern_value.find( "#" ) if ( number_sign_index < 0 ): new_filename = pattern_value else: start_of_name = pattern_value[:number_sign_index] rest_of_string = pattern_value[number_sign_index:] num_number_signs = 1 while True: if ( len(rest_of_string) <= 1 ): break if ( rest_of_string[1] == "#" ): num_number_signs = num_number_signs + 1 rest_of_string = rest_of_string[1:] else: break end_of_name = rest_of_string[1:] print "start_of_name =", start_of_name print "num_number_signs =", num_number_signs print "end_of_name =", end_of_name format_string = "%%s%%0%dd%%s" % ( num_number_signs ) print "format_string =", format_string new_filename = format_string % ( start_of_name, last_datafile_number + 1, end_of_name ) datafile_directory_value = datafile_directory.GetValue() new_pathname = os.path.join( datafile_directory_value, new_filename ) #---- next_filename_text_widget = right_panel.status_panel.next_filename_text next_filename_text_widget.SetLabel( new_pathname ) return #---- def dbdet_total_num_frames_callback_function( nf, widget, args, value ): ts_print( \ "dbdet_total_num_frames_callback_function() invoked. value = %d", value ) _dbdet.fetch_image_frame = True MpWx._Value_update( nf, widget, args, value ) return #---- def dbdet_status_callback_function( nf, widget, args, value ): ts_print( "dbdet_status_callback_function() invoked. value = %x", value ) _dbdet.no_status_change_since_start = False MpWx._Value_update( nf, widget, args, value ) _dbdet.detector_status = value if ( value == 0 ): if ( _dbdet.number_of_frames > 1 ): text = "Waiting for start" color = "blue" else: text = "Idle" color = "green" elif ( value & 4 ): text = "Correction measurement" color = "orange" elif ( value & 2 ): text = "Correcting" color = "red" elif ( value & 1 ): text = "Acquiring" color = "red" else: text = "Unknown" color = "purple" status_text = widget.parent.status_text status_text.SetLabel( text ) status_text.SetForegroundColour( color ) #------------------------------------------------------------------------------ class DbdetContrastPanel(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 = DbdetFloatValidator() ) 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 = DbdetFloatValidator() ) 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 = _dbdet.frame.image_tab.wxt_panel.image_panel panel.SetGreyRampColormap( black_value, white_value ) panel.Display() def OnAutoscaleButton( self, event ): panel = _dbdet.frame.image_tab.wxt_panel.image_panel ( mean, std_dev, min, max ) = panel.GetStatistics() black_value = round( mean - 1.0 * std_dev ) white_value = round( mean + 3.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 DbdetSequencePanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.grid = wx.GridBagSizer() self.SetSizer( self.grid ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.time_per_frame_label = \ wx.StaticText( self, -1, "Time Per Frame: " ) self.grid.Add( self.time_per_frame_label, pos=(0,0), \ flag=wx.ALIGN_CENTER ) self.time_per_frame_ctrl = wx.TextCtrl( self, \ validator = DbdetFloatValidator() ) self.grid.Add( self.time_per_frame_ctrl, pos=(0,1), \ border=5, flag=wx.RIGHT ) self.time_per_frame_units = wx.StaticText( self, -1, "seconds" ) self.grid.Add( self.time_per_frame_units, pos=(0,2), \ flag=wx.ALIGN_CENTER ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.number_of_frames_label = \ wx.StaticText( self, -1, "Number of Frames: " ) self.grid.Add( self.number_of_frames_label, pos=(1,0), \ flag=wx.ALIGN_CENTER ) self.number_of_frames_ctrl = wx.TextCtrl( self, \ validator = DbdetIntValidator() ) self.grid.Add( self.number_of_frames_ctrl, pos=(1,1), \ border=5, flag=wx.RIGHT ) #------------------------------------------------------------------------------ class DbdetSaveFilePanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.grid = wx.GridBagSizer() self.SetSizer( self.grid ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.save_button = wx.Button( self, -1, "Save File", (10,10) ) self.grid.Add( self.save_button, pos=(0,0), \ flag=wx.ALIGN_CENTER ) self.Bind( wx.EVT_BUTTON, self.OnSaveButton, self.save_button ) def OnSaveButton( self, event ): print "OnSaveButton() invoked." wildcard = "SMV format (*.smv)|*.smv|" \ "RAW format (*.raw)|*.raw" dialog = wx.FileDialog( self, message="Save image as ...", defaultDir=os.getcwd(), defaultFile="", wildcard=wildcard, style=wx.SAVE ) dialog.SetFilterIndex(0) status = dialog.ShowModal() if ( status == wx.ID_OK ): filename = dialog.GetPath() print "Saving to file", filename filter_selection = dialog.GetFilterIndex() print "filter_selection =", filter_selection if ( filter_selection == 0 ): file_format = Mp.MXT_IMAGE_FILE_SMV elif ( filter_selection == 1 ): file_format = Mp.MXT_IMAGE_FILE_SMV else: raise Mp.Illegal_Argument_Error, \ "Illegal filter selection %d" % filter_selection _dbdet.image_frame = _dbdet.ad_record.transfer_frame( \ Mp.MXFT_AD_IMAGE_FRAME, \ _dbdet.image_frame ) _dbdet.image_frame.write_file( file_format, filename ) dialog.Destroy() #------------------------------------------------------------------------------ class DbdetOptionsPanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.grid = wx.GridBagSizer() self.SetSizer( self.grid ) row = 0 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - self.options_label = wx.StaticText( self, -1, "Options" ) self.grid.Add( self.options_label, pos=(row,0), border=20, flag=wx.ALIGN_CENTER ) self.grid.SetItemSpan( self.options_label, (1,3) ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if 0: row += 1 self.skip_first_frame_cb = wx.CheckBox( self, \ -1, "Skip First Frame" ) self.skip_first_frame_cb.SetValue(True) self.grid.Add( self.skip_first_frame_cb, pos=(row,0), border=20, flag=(wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row += 1 self.spacer = wx.StaticText( self, -1, " " ) self.grid.Add( self.spacer, pos=(row,0), border=0 ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row += 1 self.smooth_cb = wx.CheckBox( self, -1, "Smooth images" ) self.grid.Add( self.smooth_cb, pos=(row,0), border=10, flag=(wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT) ) self.smooth_cb.Bind( wx.EVT_CHECKBOX, self.OnSmoothCheckBox, self.smooth_cb ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row += 1 self.moving_average_cb = \ wx.CheckBox( self, -1, "Moving average: " ) self.grid.Add( self.moving_average_cb, pos=(row,0), border=10, flag=(wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT) ) self.moving_average_cb.Bind( wx.EVT_CHECKBOX, self.OnMovingAvgCheckBox, self.moving_average_cb ) self.moving_average_value_string = \ wx.TextCtrl( self, validator = DbdetIntValidator() ) self.grid.Add( self.moving_average_value_string, pos=(row,1), border=10, flag=wx.ALIGN_CENTER ) self.moving_average_value_label = \ wx.StaticText( self, -1, " # in average" ) self.grid.Add( self.moving_average_value_label, pos=(row,2), border=10, flag=wx.ALIGN_CENTER ) #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - row += 1 options = ['Collect Raw Images', 'Collect Raw - Background', 'Collect Corrected Images', 'Collect Background Images'] self.collect_choice = wx.Choice( self, wx.ID_ANY, choices=options ) self.collect_choice.Bind( wx.EVT_CHOICE, self.OnCollectChoice ) self.grid.Add( self.collect_choice, pos=(row,0), border=10, flag=wx.ALIGN_CENTER, span=(1,3) ) flags = _dbdet.ad_record.get_correction_flags() if ( flags & 0x4 ): self.collect_choice.SetSelection(1) else: self.collect_choice.SetSelection(0) #- - - row = row + 1 self.spacer = wx.StaticText( self, -1, " " ) self.grid.Add( self.spacer, pos=(row,0), border = 5 ) #- - - row = row + 1 self.helios_flags_label = wx.StaticText( self, \ -1, "Helios Flags: " ) self.grid.Add( self.helios_flags_label, pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) hf_name = "%s.helios_flags" % ( _dbdet.remote_ad_name ) self.helios_flags_value = MpWx.Value( self, _dbdet.server_record, hf_name, function = dbdet_helios_flags_callback_function) self.helios_flags_value.SetForegroundColour( "blue" ) self.grid.Add( self.helios_flags_value, pos=(row,1), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) helios_flags_choices = \ [ 'Timed Exposure', 'Continuous Exposure' ] self.helios_flags_selector = wx.Choice( self, -1, \ choices=helios_flags_choices ) self.helios_flags_selector.Bind( wx.EVT_CHOICE, self.OnHeliosFlagsChoice ) self.grid.Add( self.helios_flags_selector, pos=(row,2), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) flags_value = self.helios_flags_value.nf.get() print "init: flags_value =", flags_value if ( flags_value & 0x4 ): print "init: selecting continuous." self.helios_flags_selector.SetSelection(1) else: print "init: selecting timed." self.helios_flags_selector.SetSelection(0) def OnSmoothCheckBox( self, event ): checked = self.smooth_cb.IsChecked() print "smooth_cb: checked =", checked if ( checked ): _dbdet.smooth_images = True else: _dbdet.smooth_images = False def OnMovingAvgCheckBox( self, event ): checked = self.moving_average_cb.IsChecked() print "moving_average_cb: checked =", checked if ( checked ): _dbdet.collect_moving_average = True else: _dbdet.collect_moving_average = False def OnCollectChoice( self, event ): choice = self.collect_choice.GetSelection() # Discard the moving average. _dbdet.moving_average_list = [] if ( choice == 0 ): _dbdet.ad_record.set_correction_flags( 0x0 ) _dbdet.acquire_dark_current_frame = False elif ( choice == 1 ): _dbdet.ad_record.set_correction_flags( 0x7 ) _dbdet.acquire_dark_current_frame = False elif ( choice == 2 ): _dbdet.ad_record.set_correction_flags( 0xf ) _dbdet.acquire_dark_current_frame = False elif ( choice == 3 ): _dbdet.ad_record.set_correction_flags( 0x0 ) _dbdet.acquire_dark_current_frame = True else: error_message = "Illegal choice %d returned." % choice raise ValueError, error_message def OnHeliosFlagsChoice( self, event ): selection = self.helios_flags_selector.GetSelection() print "HeliosFlags selection =", selection nf = self.helios_flags_value.nf old_value = nf.get() old_value = int( old_value ) print "HeliosFlags old_value =", old_value if ( selection == 0 ): new_value = ( old_value & (~4) ) else: new_value = old_value | 4 print "HeliosFlags new_value =", new_value if ( old_value != new_value ): print "HeliosFlags changing to", new_value nf.put( new_value ) else: print "HeliosFlags staying at", new_value #--------------------- def dbdet_helios_flags_callback_function( nf, widget, args, value ): MpWx._Value_update( nf, widget, args, value ) try: options_widget = widget.GetParent() choice_widget = options_widget.helios_flags_selector if ( value & 4 ): choice_widget.SetSelection(1) else: choice_widget.SetSelection(0) except: print "Skipping incomplete choice widget." #------------------------------------------------------------------------------ class DbdetDatafilePanel(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" % _dbdet.remote_ad_name self.spacer = wx.StaticText( self, -1, " " ) self.grid.Add( self.spacer, pos=(row,1) ) self.directory_value = DbdetDatafileDirectory( 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" % _dbdet.remote_ad_name self.pattern_value = MpWx.ValueEntry( self, _dbdet.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, "Last Filename:" ) self.grid.Add( self.filename_label, pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) ) filename_nf_name = "%s.datafile_name" % _dbdet.remote_ad_name self.filename_value = MpWx.Value( self, _dbdet.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.last_file_number_label = \ wx.StaticText( self, -1, "Last Datafile Number:" ) self.grid.Add( self.last_file_number_label, pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) last_file_number_nf_name = \ "%s.datafile_number" % _dbdet.remote_ad_name self.last_file_number_value = MpWx.ValueEntry( self, _dbdet.server_record, last_file_number_nf_name, function = dbdet_update_next_filename_callback_function, args = self, size=(200,-1) ) self.grid.Add( self.last_file_number_value, pos=(row,2), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) #--------------------------------------------------------- # The contents of the Last Datafile Number field may be # looked at before all of the GUI is initialized, so we # explicitly make sure that it has been initialized. last_file_number_nf = self.last_file_number_value.nf current_value = last_file_number_nf.get() current_value = str(current_value) self.last_file_number_value.SetValue( current_value ) #- - - 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" % _dbdet.remote_ad_name self.autoselect_number_value = MpWx.ValueEntry( self, _dbdet.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" % _dbdet.remote_ad_name self.allow_overwrite_value = MpWx.ValueEntry( self, _dbdet.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 ) #- - - row = row + 1 self.spacer_label = wx.StaticText( self, -1, " " ) self.grid.Add( self.spacer_label, pos=(row,0), flag=(wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL), border = 5 ) #--------------------------------------------------------- self.SetSizer( self.grid ) #------------------------------------------------------------------------------ class DbdetDatafileDirectory(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" % ( _dbdet.remote_ad_name ) self.nf = Mp.Net( _dbdet.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 = \ _dbdet.record_list.get_record( "mx_remote_dir" ) self.local_dir_record = \ _dbdet.record_list.get_record( "mx_local_dir" ) except: self.remote_dir_record = None self.local_dir_record = None # # Fetch the initial value of the field. # function = dbdet_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 = dbdet_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 = \ dbdet_transform_path( self, new_path, True ) self.nf.put( new_path ) self.SetValue( new_path ) dialog.Destroy() #--- def dbdet_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 = dbdet_transform_path( widget, value, False ) widget.SetValue( value ) widget.SetSize( widget.GetBestSize() ) #--- def dbdet_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 "dbdet_transform_path: old_prefix = '%s', new_prefix = '%s'" \ % ( old_prefix, new_prefix ) print "dbdet_transform_path: old_filename = '%s', new_filename = '%s'" \ % ( old_filename, new_filename ) return new_filename #------------------------------------------------------------------------------ #============================================================================= # # The DbdetTimer class is used to implement periodic checks of the hardware. # class DbdetTimer(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 ): # ts_print( "vvv======= OnTimerEvent() invoked =======vvv" ) try: _dbdet.record_list.wait_for_messages( 0.1 ) except Mp.Timed_Out_Error: pass if ( _dbdet.number_of_frames > 1 ): if ( _dbdet.detector_status == 0 ): # Suppress extraneous starts. if ( _dbdet.no_status_change_since_start ): return # Start the detector again. ts_print( "DbdetTimer: About to start()." ) current_time = time.time() ts_print( "Time since last start = %f", current_time - _dbdet.last_start_time ) _dbdet.last_start_time = current_time _dbdet.ad_record.start() _dbdet.number_of_frames -= 1 _dbdet.no_status_change_since_start = True # ts_print( "^^^======= OnTimerEvent() complete ======^^^" ) #============================================================================= class DbdetFloatValidator(wx.PyValidator): ''' DbdetFloatValidator() checks for valid numerical characters in a text entry field. It also permits editing characters like backspace, delete, and so forth. ''' def __init__( self ): wx.PyValidator.__init__(self) self.valid_keycodes = [ wx.WXK_DELETE, wx.WXK_BACK, \ wx.WXK_HOME, wx.WXK_END, \ wx.WXK_LEFT, wx.WXK_RIGHT, \ wx.WXK_INSERT ] self.valid_chars = '0123456789-.eE' self.Bind( wx.EVT_CHAR, self.OnChar ) def Clone( self ): return DbdetFloatValidator() def Validate( self, window ): return True def TransferToWindow( self ): return True def TransferFromWindow( self ): return True def OnChar( self, event ): keycode = event.GetKeyCode() # Is this a valid keycode? if ( keycode in self.valid_keycodes ): # This keycode is valid so let it through. event.Skip() return # Is this a valid character for a number? try: key = chr( keycode ) if ( key in self.valid_chars ): # This key is valid, so let it through. event.Skip() return # This key is not valid. pass except: # The keycode was not in the valid range for chr(). pass # # If we get here, the key the user typed was not valid # for editing a floating point number, so we discard # the keycode event without passing it on. # # # FIXME: We should beep here to tell the user that # the key is invalid. # return #------------------------------------------------------------------------ class DbdetIntValidator(DbdetFloatValidator): def __init__( self ): DbdetFloatValidator.__init__(self) self.valid_chars = '0123456789-' def Clone( self ): return DbdetIntValidator() #------------------------------------------------------------------------ def ts_print( format, *args ): timestamp = datetime.datetime.today() timestamp_string = "%02d:%02d:%02d.%06d" % ( timestamp.hour, \ timestamp.minute, \ timestamp.second, \ timestamp.microsecond ) print timestamp_string, print format % args #------------------------------------------------------------------------ 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_FLOOD_FIELD_FRAME else: msg = "Illegal server frame type %d requested." % selection raise Mp.CorruptDataStructureError, msg return server_frame_type #------------------------------------------------------------------------ def discard_frame( frame_number ): ad = _dbdet.ad_record ad.setup_frame( _dbdet.image_frame ) ad.readout_frame( frame_number ) #------------------------------------------------------------------------ def get_frame_from_server( frame_type, 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_FLOOD_FIELD_FRAME ): frame_name = 'flood field' else: msg = "Unsupported frame type %x requested." % frame_type raise Mp.IllegalArgumentError, msg ad = _dbdet.ad_record if ( frame_type == Mp.MXFT_AD_IMAGE_FRAME ): ad.setup_frame( _dbdet.image_frame ) ad.readout_frame( frame_number ) ad.correct_frame() ad.transfer_frame( frame_type, _dbdet.image_frame ) else: ad.transfer_frame( frame_type, _dbdet.image_frame ) #------------------------------------------------------------------------ def get_frame_from_server_and_rebin( frame_type, frame_number ): ts_print( "get_frame_from_server_and_rebin() invoked for frame %d.", frame_number ) get_frame_from_server( frame_type, frame_number ) ts_print( "Finished reading frame %d.", frame_number ) processed_image_frame = _dbdet.image_frame print "gffsar: processed_image_frame.framesize =", \ processed_image_frame.framesize if ( _dbdet.smooth_images ): numpy_image = processed_image_frame.to_numpy() numpy_image = scipy.ndimage.filters.median_filter( \ numpy_image, size=5 ) processed_image_frame.from_numpy( numpy_image ) processed_image_frame = rebin_image_frame( processed_image_frame ) if ( _dbdet.collect_moving_average ): numpy_image = processed_image_frame.to_numpy() # Add this frame to the moving average. _dbdet.moving_average_list.append( numpy_image ) # If the list contains more items than should be # in the moving average, discard the excess items # at the start of the list. average_value_string_widget = \ _dbdet.frame.image_tab.right_panel.options_panel.moving_average_value_string num_in_average = average_value_string_widget.GetValue() num_in_average = int( num_in_average ) list_length = len( _dbdet.moving_average_list ) diff = list_length - num_in_average if ( diff > 0 ): _dbdet.moving_average_list[0:diff] = [] list_length = len( _dbdet.moving_average_list ) # Now compute the average of the items in the list. image_shape = numpy_image.shape numpy_image = numpy.zeros( image_shape ) for i in range(list_length): numpy_image = numpy_image \ + _dbdet.moving_average_list[i] numpy_image = numpy_image / float(list_length) numpy_image = numpy_image.astype( 'uint16' ) processed_image_frame.from_numpy( numpy_image ) _dbdet.processed_image_frame = processed_image_frame wxt_panel = _dbdet.frame.image_tab.wxt_panel wxt_panel.SetData( _dbdet.processed_image_frame ) wxt_panel.Display() ts_print( "get_frame_from_server_and_rebin() complete." ) #------------------------------------------------------------------------ def rebin_image_frame( mp_image_frame ): original_frame = mp_image_frame if 0: original_frame.read_file( Mp.MXT_IMAGE_FILE_SMV, \ "d:/docume~1/lavender/wmlsnap1.smv" ) rebinned_256x256_frame = original_frame.rebin( (256,256) ) new_frame = rebinned_256x256_frame.rebin( (512,512) ) return new_frame #============================================================================= class DbdetWxtImagePanel(wx.Panel): def __init__( self, parent ): wx.Panel.__init__( self, parent ) self.parent = parent self.box = wx.BoxSizer( wx.VERTICAL ) self.image_panel = WxtImage.ImagePanel( self, size=(800,800) ) self.box.Add( self.image_panel, 20, wx.EXPAND, border=10 ) self.image_position = wx.StaticText( self, -1, label="XYZZY" ) self.box.Add( self.image_position, 1, wx.ALIGN_LEFT, border=10 ) self.SetSizer( self.box ) self.Bind( wx.EVT_SIZE, self.OnSize ) self.image_panel.SetPositionWindow( self.image_position ) self.contrast_panel = DbdetContrastPanel( self ) self.box.Add( self.contrast_panel, 1, wx.ALIGN_LEFT, border=0 ) def SetData( self, mp_image_frame ): binary_string = mp_image_frame.get_image_data() raw_pil_image = Image.fromstring( "F", \ mp_image_frame.framesize, \ binary_string, \ "raw", "F;16N" ) self.image_panel.SetData( raw_pil_image ) def Display( self ): # print "DbdetWxtImagePanel: Display() invoked." self.image_panel.Display() def OnSize( self, event ): # print "DbdetWxtImagePanel: OnSize(): size =", self.GetSize() event.Skip()