def __init__(self, config=None, parameters_file_name=None, testing_mode=False, show_gui=True, **kwds): super().__init__(**kwds) self.modules = [] self.module_name = "core" self.qt_settings = QtCore.QSettings( "storm-control", "hal4000" + config.get("setup_name").lower()) self.queued_messages = deque() self.queued_messages_timer = QtCore.QTimer(self) self.running = True # This is solely for the benefit of unit tests. self.sent_messages = [] self.strict = config.get("strict", False) self.queued_messages_timer.setInterval(0) self.queued_messages_timer.timeout.connect(self.handleSendMessage) self.queued_messages_timer.setSingleShot(True) # Initialize messages. halMessage.initializeMessages() # Load all the modules. print("Loading modules") # # For HAL it is easier to just use a list of modules, but at initialization # we also send a dictionary with the module names as keys to all of the # modules # # In testing mode the testing.testing module may use the other modules to # spoof the message sources. # # During normal operation most inter-module communication is done using # messages. Modules may also request functionalities from other modules # that they can use to do specific tasks, such as daq output or displaying # the images from a camera. # all_modules = {} if testing_mode: all_modules["core"] = self else: all_modules["core"] = True # # Need to load HAL's main window first so that other GUI windows will # have the correct Qt parent. # module_names = sorted(config.get("modules").getAttrs()) module_names.insert(0, module_names.pop(module_names.index("hal"))) for module_name in module_names: print(" " + module_name) # Get module specific parameters. module_params = config.get("modules").get(module_name) # Add the 'root' parameters to this module parameters # so that they are visible to the module. for root_param in config.getAttrs(): if (root_param != "modules"): module_params.add(root_param, config.getp(root_param)) # Load the module. a_module = importlib.import_module( module_params.get("module_name")) a_class = getattr(a_module, module_params.get("class_name")) a_object = a_class(module_name=module_name, module_params=module_params, qt_settings=self.qt_settings) # If this is HAL's main window set the HalDialog qt_parent class # attribute so that any GUI QDialogs will have the correct Qt parent. if (module_name == "hal"): halDialog.HalDialog.qt_parent = a_object.view self.modules.append(a_object) if testing_mode: all_modules[module_name] = a_object else: all_modules[module_name] = True print("") # Connect signals. for module in self.modules: module.newMessage.connect(self.handleMessage) # Create messages. # # We do it this way with finalizers because otherwise all of these messages # would get queued first and the modules would not have a chance to insert # messages in between these messages. # # The actual sequence of sent messages is: # # 1. "configure1", tell modules to finish configuration. # The message includes a dictionary of the names of # all modules that were loaded. # # 2. "configure2", gives the modules a chance to 'react' # based on what happened during configure1. # # 3. "configure3", gives the modules a chance to 'react' # based on what happened during configure1. # # 4. "new parameters file", initial parameters (if any). # # 5. "start", tell the modules to start. # This is the point where any GUI modules that are # visible should call show(). # message_chain = [] # configure1. message_chain.append( halMessage.HalMessage(source=self, m_type="configure1", data={"all_modules": all_modules})) # configure2. message_chain.append( halMessage.HalMessage(source=self, m_type="configure2")) # configure3. message_chain.append( halMessage.HalMessage(source=self, m_type="configure3")) # update default parameters. if parameters_file_name is not None: message_chain.append( halMessage.HalMessage(source=self, m_type="new parameters file", data={ "parameters filename": parameters_file_name, "is_default": True })) # start. # # It is safe to stop blocking Qt's last window closed behavior after # this message as HAL's main window will be open. # # If we run HAL from another module, in testing for example, app might # be none. # if app is not None: message_chain.append( halMessage.HalMessage( source=self, m_type="start", data={"show_gui": show_gui}, sync=True, finalizer=lambda: app.setQuitOnLastWindowClosed(True))) else: message_chain.append( halMessage.HalMessage(source=self, m_type="start", data={"show_gui": show_gui}, sync=True)) message_chain.append(halMessage.SyncMessage(source=self)) self.handleMessage( halMessage.chainMessages(self.handleMessage, message_chain))
def __init__(self, config = None, parameters_file_name = None, testing_mode = False, show_gui = True, **kwds): super().__init__(**kwds) self.modules = [] self.module_name = "core" self.qt_settings = QtCore.QSettings("storm-control", "hal4000" + config.get("setup_name").lower()) self.queued_messages = deque() self.queued_messages_timer = QtCore.QTimer(self) self.running = True # This is solely for the benefit of unit tests. self.sent_messages = [] self.strict = config.get("strict", False) self.queued_messages_timer.setInterval(0) self.queued_messages_timer.timeout.connect(self.handleSendMessage) self.queued_messages_timer.setSingleShot(True) # Initialize messages. halMessage.initializeMessages() # In strict mode we all workers must finish in 60 seconds. if self.strict: halModule.max_job_time = 60000 # Load all the modules. print("Loading modules") # # For HAL it is easier to just use a list of modules, but at initialization # we also send a dictionary with the module names as keys to all of the # modules # # In testing mode the testing.testing module may use the other modules to # spoof the message sources. # # During normal operation most inter-module communication is done using # messages. Modules may also request functionalities from other modules # that they can use to do specific tasks, such as daq output or displaying # the images from a camera. # all_modules = {} if testing_mode: all_modules["core"] = self else: all_modules["core"] = True # # Need to load HAL's main window first so that other GUI windows will # have the correct Qt parent. # module_names = sorted(config.get("modules").getAttrs()) module_names.insert(0, module_names.pop(module_names.index("hal"))) for module_name in module_names: print(" " + module_name) # Get module specific parameters. module_params = config.get("modules").get(module_name) # Add the 'root' parameters to this module parameters # so that they are visible to the module. for root_param in config.getAttrs(): if (root_param != "modules"): module_params.add(root_param, config.getp(root_param)) # Load the module. a_module = importlib.import_module(module_params.get("module_name")) a_class = getattr(a_module, module_params.get("class_name")) a_object = a_class(module_name = module_name, module_params = module_params, qt_settings = self.qt_settings) # If this is HAL's main window set the HalDialog qt_parent class # attribute so that any GUI QDialogs will have the correct Qt parent. if (module_name == "hal"): halDialog.HalDialog.qt_parent = a_object.view self.modules.append(a_object) if testing_mode: all_modules[module_name] = a_object else: all_modules[module_name] = True print("") # Connect signals. for module in self.modules: module.newMessage.connect(self.handleMessage) # Create messages. # # We do it this way with finalizers because otherwise all of these messages # would get queued first and the modules would not have a chance to insert # messages in between these messages. # # The actual sequence of sent messages is: # # 1. "configure1", tell modules to finish configuration. # The message includes a dictionary of the names of # all modules that were loaded. # # 2. "configure2", gives the modules a chance to 'react' # based on what happened during configure1. # # 3. "configure3", gives the modules a chance to 'react' # based on what happened during configure2. # # 4. "new parameters file", initial parameters (if any). # # 5. "start", tell the modules to start. # This is the point where any GUI modules that are # visible should call show(). # message_chain = [] # configure1. message_chain.append(halMessage.HalMessage(source = self, m_type = "configure1", data = {"all_modules" : all_modules})) # configure2. message_chain.append(halMessage.HalMessage(source = self, m_type = "configure2")) # configure3. message_chain.append(halMessage.HalMessage(source = self, m_type = "configure3")) # update default parameters. if parameters_file_name is not None: message_chain.append(halMessage.HalMessage(source = self, m_type = "new parameters file", data = {"parameters filename" : parameters_file_name, "is_default" : True})) # start. # # It is safe to stop blocking Qt's last window closed behavior after # this message as HAL's main window will be open. # # If we run HAL from another module, in testing for example, app might # be none. # if app is not None: message_chain.append(halMessage.HalMessage(source = self, m_type = "start", data = {"show_gui" : show_gui}, sync = True, finalizer = lambda : app.setQuitOnLastWindowClosed(True))) else: message_chain.append(halMessage.HalMessage(source = self, m_type = "start", data = {"show_gui" : show_gui}, sync = True)) message_chain.append(halMessage.SyncMessage(source = self)) self.handleMessage(halMessage.chainMessages(self.handleMessage, message_chain))