Пример #1
0
    def handleNewParameters(self, parameters, is_edit):
        """
        Sends the 'new parameters' message. 

        The updated parameters could be a modified form of the current parameters or
        it could be a different set. We use the is_edit flag to record which of these
        two it is.
        """
        if self.locked_out:
            raise halExceptions.HalException(
                "parameter change attempted while locked out.")

        # Disable the UI so the user can't change the parameters again while we
        # are processing the current change.
        self.view.enableUI(False)

        self.setLockout(True)

        # is_edit means we are sending a modified version of the current parameters.
        self.sendMessage(
            halMessage.HalMessage(m_type="new parameters",
                                  data={
                                      "parameters": parameters.copy(),
                                      "is_edit": is_edit
                                  }))
Пример #2
0
def addMessage(name, validator = {}, check_exists = True):
    """
    Modules should call this function at initialization to add additional messages.
    """
    global valid_messages
    if check_exists and name in valid_messages:
        raise halExceptions.HalException("Message " + name + " already exists!")
    valid_messages[name] = validator
Пример #3
0
    def handleWorkerTimer(self):
        """
        If this timer fires that means the worker took longer than
        expected to complete a task, so it is probably hung.

        Not sure whether we handle this or just crash, but for now 
        we're going with crash. This may be all that we can do anyway
        as there is no way to kill a QRunnable that is stuck.
        """
        # Print a complete traceback including what all the threads were doing.
        print("Full Traceback With Threads:")
        faulthandler.dump_traceback()
        print("")

        e_string = "HALWorker for '" + self.module_name + "' module timed out handling '" + self.worker.message.m_type + "'!"
        raise halExceptions.HalException(e_string)
Пример #4
0
    def newShutters(self, shutters_filename):
        """
        Called when we get new parameters, which will have a shutters file,
        and also when the user loads a new shutters file for the existing
        parameters.
        """

        filename_to_parse = None
        path_filename = os.path.join(self.xml_directory, shutters_filename)

        # Check if the shutters file exists in the current directory.
        if os.path.exists(shutters_filename):
            filename_to_parse = shutters_filename

        # Check if the shutters exists in the current XML directory.
        elif os.path.exists(path_filename):
            filename_to_parse = path_filename

        else:
            raise halExceptions.HalException("Could not load find '" +
                                             shutters_filename + "' or '" +
                                             path_filename + "'")

        # Save possibly updated shutter file information.
        self.parameters.set("shutters", shutters_filename)

        # Parse XML to get shutter information, waveforms, etc.
        [self.shutters_info, waveforms,
         oversampling] = xmlParser.parseShuttersXML(self.channel_name_to_id,
                                                    filename_to_parse)

        self.waveforms = []
        for i, channel in enumerate(self.channels):
            # Channels determine whether or not they are used for filming based on the waveform.
            channel.setUsedForFilm(waveforms[i])

            # Channels create DaqWaveform objects (or not) based on the waveform.
            self.waveforms.extend(
                channel.getDaqWaveforms(waveforms[i], oversampling))

        # Send shutters info to other modules
        self.guiMessage.emit(
            halMessage.HalMessage(
                m_type="configuration",
                data={"properties": {
                    "shutters info": self.shutters_info
                }}))
Пример #5
0
    def handleMessage(self, message):
        """
        Adds a message to the queue of images to send.
        """
        # Check the message and it to the queue.
        if self.strict:
            if not message.m_type in halMessage.valid_messages:
                msg = "Invalid message type '" + message.m_type
                msg += "' received from " + message.getSourceName()
                raise halExceptions.HalException(msg)

            validator = halMessage.valid_messages[message.m_type].get("data")
            halMessage.validateData(validator, message)

        message.logEvent("queued")

        self.queued_messages.append(message)

        # Start the message timer, if it is not already running.
        self.startMessageTimer()
Пример #6
0
    def getQItemByValue(self, value):
        """
        This returns a QStandardItem including it's data from the model.

        value can a string or an integer.
        """
        if isinstance(value, str):
            items = self.model.findItems(value)

            #
            # FIXME: Not sure we actually want to throw an error here, maybe we
            #        should just return a list of matching parameters?
            #
            if (len(items) > 1):
                raise halExceptions.HalException(
                    "Found " + str(len(items)) +
                    " parameter files with the requested name!")
            elif (len(items) == 1):
                return items[0]
        else:
            return self.model.item(value)
Пример #7
0
    def processMessage(self, message):

        if message.isType("configure1"):
            self.newMessage.emit(
                halMessage.HalMessage(source=self,
                                      m_type="add to ui",
                                      data=self.configure_dict))

        elif message.isType("configure2"):
            self.view.copyDefaultParameters()
            self.view.markCurrentAsInitialized()

        elif message.isType("get parameters"):
            p = self.view.getParameters(message.getData()["index or name"])
            if p is None:
                message.addResponse(
                    halMessage.HalMessageResponse(source=self.module_name,
                                                  data={"found": False}))
            else:
                message.addResponse(
                    halMessage.HalMessageResponse(source=self.module_name,
                                                  data={
                                                      "parameters": p,
                                                      "found": True
                                                  }))

        elif message.isType("initial parameters"):

            # It is okay for other modules to just send their parameters as we make
            # a copy before storing them in this module.
            self.view.updateCurrentParameters(
                message.getSourceName(),
                message.getData()["parameters"].copy())

        elif message.isType("new parameters file"):

            # Ignore this message if the UI is disabled and send a warning.
            if not self.view.getEnabled():
                msg = "Parameters files cannot be added during editting / filming"
                message.addError(
                    halMessage.HalMessageError(source=self.module_name,
                                               message=msg))
                return

            data = message.getData()

            # Check if these parameters should be default parameters. For now
            # anyway this should only be possible at initialization.
            is_default = False
            if "is default" in data:
                is_default = data["is default"]

            # Process new parameters file.
            self.view.newParametersFile(data["filename"], is_default)

        elif message.isType("parameters changed"):
            self.waiting_on.remove(message.getSourceName())

            if message.getData() is not None:
                self.view.updateCurrentParameters(
                    message.getSourceName(),
                    message.getData()["new parameters"].copy())

            # All modules have finished changing parameters.
            if (len(self.waiting_on) == 0):
                self.updateComplete()

        elif message.isType("set parameters"):
            if self.locked_out:
                raise halExceptions.HalException(
                    "'set parameters' received while locked out.")
            [found, current
             ] = self.view.setParameters(message.getData()["index or name"])
            message.addResponse(
                halMessage.HalMessageResponse(source=self.module_name,
                                              data={
                                                  "current": current,
                                                  "found": found
                                              }))

        elif message.isType("start film"):
            self.view.enableUI(False)

        elif message.isType("stop film"):
            self.view.enableUI(True)

        elif message.isType("wait for"):
            if self.module_name in message.getData()["module names"]:
                self.wait_for.append(message.getSourceName())
Пример #8
0
    def setCameraFunctionality(self, camera_functionality):
        """
        This method gets called when the view changes it's current feed. The
        sequence is that a 'get functionality' message is sent. When
        the display module gets the updated functionality it calls this 
        method.
        """

        # Give the correct functionality to the shutter button.
        if camera_functionality.isCamera():
            self.ui.shutterButton.setCameraFunctionality(camera_functionality)
        else:
            self.ui.shutterButton.setCameraFunctionality(camera_functionality.getCameraFunctionality())

        # A sanity check that this is the right feed.
        assert (self.getFeedName() == camera_functionality.getCameraName())

        # A sanity check that the old camera functionality is disconnected.
        if self.cam_fn is not None:
            try:
                self.cam_fn.newFrame.disconnect(self.handleNewFrame)
            except TypeError:
                pass
            else:
                msg = "Old camera functionality was not disconnected."
                raise halExceptions.HalException(msg)
                
        # Connect new camera functionality.
        self.cam_fn = camera_functionality
        self.cam_fn.newFrame.connect(self.handleNewFrame)

        #
        # Add a sub-section for this camera / feed if we don't already have one.
        #
        # The camera / feed provides default values about how it's images should
        # be displayed. These are what we'll use if don't already have some other
        # values.
        #
        parameters_from_file = None
        need_to_initialize = False

        # Check if we have anything at all for this feed.
        if not self.parameters.has(self.getFeedName()):
            need_to_initialize = True

        #
        # Check if all we have are values from a parameter file that we loaded.
        # In this case we will only have some of the parameters and some of
        # them will not be of the correct type.
        #
        # We're doing this by checking for "max_intensity" as this should not
        # have been saved, so if it exists then the parameters must have been
        # initialized properly.
        #
        # In order to initialize them properly we make a copy of the current
        # values, then delete the section, recreate it correctly and update
        # it with the current values.
        #
        else:
            feed_params = self.parameters.get(self.getFeedName())
            if not feed_params.has("max_intensity"):
                need_to_initialize = True
                parameters_from_file = feed_params.copy()
                self.parameters.delete(self.getFeedName())

        if need_to_initialize:
            self.createParameters(self.cam_fn, parameters_from_file)

        # Configure the QtCameraGraphicsItem.
        color_table = self.color_tables.getTableByName(self.getParameter("colortable"))
        self.camera_widget.newColorTable(color_table)
        self.camera_widget.newConfiguration(self.cam_fn)
        self.updateRange()

        # Configure the QtCameraGraphicsView.
        self.camera_view.newConfiguration(self.cam_fn, self.parameters.get(self.getFeedName()))

        # Color gradient.
        if self.color_gradient is not None:
            self.color_gradient.newColorTable(color_table)
        else:
            self.color_gradient = qtColorGradient.QColorGradient(colortable = color_table,
                                                                     parent = self.ui.colorFrame)
            layout = QtWidgets.QGridLayout(self.ui.colorFrame)
            layout.setContentsMargins(2,2,2,2)
            layout.addWidget(self.color_gradient)
                
        self.ui.colorComboBox.setCurrentIndex(self.ui.colorComboBox.findText(self.getParameter("colortable")[:-5]))

        # General settings.
        self.ui.rangeSlider.setRange([0.0, self.getParameter("max_intensity"), 1.0])
        self.ui.rangeSlider.setValues([float(self.getParameter("display_min")),
                                       float(self.getParameter("display_max"))])

        self.ui.syncSpinBox.setValue(self.getParameter("sync"))
Пример #9
0
    def createParameters(self, cam_fn, parameters_from_file):
        """
        Create (initial) parameters for the current feed.

        cam_fn - A camera / feed functionality object.
        parameters_from_file - The parameters that were read from the XML file.
        """
        # Check that we are not writing over something that already exists.
        if (self.parameters.has(self.getFeedName())):
            msg = "Display parameters for " + self.getFeedName() + " already exists."
            raise halExceptions.HalException(msg)

        # Create a sub-section for this camera / feed.
        p = self.parameters.addSubSection(self.getFeedName())

        # Add display specific parameters.
        p.add(params.ParameterFloat(name = "center_x",
                                    value = 0.0,
                                    is_mutable = False))

        p.add(params.ParameterFloat(name = "center_y",
                                    value = 0.0,
                                    is_mutable = False))
            
        p.add(params.ParameterSetString(description = "Color table",
                                        name = "colortable",
                                        value = self.color_tables.getColorTableNames()[0],
                                        allowed = self.color_tables.getColorTableNames()))
                        
        p.add(params.ParameterInt(description = "Display maximum",
                                  name = "display_max",
                                  value = 100))

        p.add(params.ParameterInt(description = "Display minimum",
                                  name = "display_min",
                                  value = 0))

        p.add(params.ParameterSetBoolean(name = "initialized",
                                         value = False,
                                         is_mutable = False))

        p.add(params.ParameterInt(name = "max_intensity",
                                  value = 100,
                                  is_mutable = False,
                                  is_saved = False))

        p.add(params.ParameterInt(name = "scale",
                                  value = 0,
                                  is_mutable = False))
            
        p.add(params.ParameterInt(description = "Frame to display when filming with a shutter sequence",
                                  name = "sync",
                                  value = 0))

        # Set parameters with default values from feed/camera functionality
        if cam_fn.hasParameter("colortable"):
            p.setv("colortable", cam_fn.getParameter("colortable"))
        else:
            p.setv("colortable", self.default_colortable)
        p.setv("display_max", cam_fn.getParameter("default_max"))
        p.setv("display_min", cam_fn.getParameter("default_min"))
        p.setv("max_intensity", cam_fn.getParameter("max_intensity"))

        # If they exist, update with the values that we loaded from a file.
        # Also, some parameters files will have 'extra' parameters, typically
        # sub-sections for the different feeds. We skip these here as this
        # will be handled when we change to the feed and call the
        # setCameraFunctionality() method.
        #
        if parameters_from_file is not None:
            for attr in parameters_from_file.getAttrs():
                if p.has(attr):
                    p.setv(attr, parameters_from_file.get(attr))
Пример #10
0
    def processMessage(self, message):

        if message.isType("configuration"):

            # Check for master cameras. If they exist this is an error in the setup
            # configuration.
            if ("is camera" in message.getData()["properties"]):
                if not self.allow_master:
                    m_data = message.getData()["properties"]
                    if m_data["is camera"] and m_data["is master"]:
                        raise halExceptions.HalException(
                            "Master camera detected in hardware timed setup!")

            # Check if we are the time base for the film.
            #
            # If we are and this is a fixed length film then
            # set the hardware counter appropriately.
            #
            elif message.sourceIs("timing"):
                timing_fn = message.getData()["properties"]["functionality"]
                if (timing_fn.getTimeBase() == self.module_name
                    ) and self.film_settings.isFixedLength():
                    self.hardware_timing_functionality.setFilmLength(
                        self.film_settings.getFilmLength())

        elif message.isType("configure1"):

            # Broadcast initial parameters.
            self.sendMessage(
                halMessage.HalMessage(m_type="initial parameters",
                                      data={"parameters": self.parameters}))

            # Send 'configuration' message with information about this hardware timing
            # module. This module is always a master, but is not a camera.
            p_dict = {
                "module name": self.module_name,
                "is camera": False,
                "is master": True
            }
            self.sendMessage(
                halMessage.HalMessage(m_type="configuration",
                                      data={"properties": p_dict}))

            # Get DAQ counter like functionality.
            self.sendMessage(
                halMessage.HalMessage(
                    m_type="get functionality",
                    data={
                        "name": self.configuration.get("counter_fn_name"),
                        "extra data": "counter"
                    }))

        elif message.isType("current parameters"):
            message.addResponse(
                halMessage.HalMessageResponse(
                    source=self.module_name,
                    data={"parameters": self.parameters.copy()}))

        elif message.isType("get functionality"):
            if (message.getData()["name"] == self.module_name):
                message.addResponse(
                    halMessage.HalMessageResponse(
                        source=self.module_name,
                        data={
                            "functionality": self.hardware_timing_functionality
                        }))

        elif message.isType("new parameters"):
            #
            # FIXME: We have a similar problem here as with timing.timing. We don't know
            #        the allowed FPS range for the cameras based on their new parameters
            #        at this point. By the time we do know at 'updated parameters' it is
            #        to late to change the allowed range that settings.settings will show
            #        in the parameter editor GUI.
            #
            message.addResponse(
                halMessage.HalMessageResponse(
                    source=self.module_name,
                    data={"old parameters": self.parameters.copy()}))
            p = message.getData()["parameters"].get(self.module_name)
            self.parameters.setv("fps", p.get("fps"))
            self.hardware_timing_functionality.setFPS(p.get("fps"))
            message.addResponse(
                halMessage.HalMessageResponse(
                    source=self.module_name,
                    data={"new parameters": self.parameters}))

        elif message.isType("start"):
            if self.hardware_timing_functionality is None:
                raise halExceptions.HalException(
                    "no counter functionality available for hardware timing.")

        elif message.isType("start camera"):
            # This message comes from film.film. This module behaves
            # like a master camera.
            if message.getData()["master"]:
                self.hardware_timing_functionality.startCounter()

        elif message.isType("start film"):
            # This message comes from film.film, we save the film settings
            # but don't actually do anything until we get a 'configuration'
            # message from timing.timing.
            self.film_settings = message.getData()["film settings"]

        elif message.isType("stop camera"):
            # This message comes from film.film. This module behaves
            # like a master camera.
            if message.getData()["master"]:
                self.hardware_timing_functionality.stopCounter()

        elif message.isType("stop film"):
            message.addResponse(
                halMessage.HalMessageResponse(
                    source=self.module_name,
                    data={"parameters": self.parameters.copy()}))
Пример #11
0
    def processMessage(self, message):

        if message.isType("change directory"):
            self.view.setDirectory(message.getData()["directory"])
                    
        elif message.isType("configuration"):
            if message.sourceIs("feeds"):
                self.camera_functionalities = []
                for name in message.getData()["properties"]["feed names"]:
                    self.sendMessage(halMessage.HalMessage(m_type = "get functionality",
                                                           data = {"name" : name}))
                    self.number_fn_requested += 1

            elif message.sourceIs("illumination"):
                properties = message.getData()["properties"]
                if "shutters filename" in properties:
                    self.view.setShutters(properties["shutters filename"])

            elif message.sourceIs("mosaic"):
                #
                # We need to keep track of the current value so that
                # we can save this in the tif images / stacks.
                #
                self.pixel_size = message.getData()["properties"]["pixel_size"]
                    
            elif message.sourceIs("timing"):
                #
                # We'll get this message from timing.timing, the part we are interested in is
                # the timing functionality which we will use both to update the frame counter
                # and to know when a fixed length film is complete.
                #
                self.timing_functionality = message.getData()["properties"]["functionality"]
                self.timing_functionality.newFrame.connect(self.handleNewFrame)
                self.timing_functionality.stopped.connect(self.stopFilmingLevel1)

        elif message.isType("configure1"):
            self.sendMessage(halMessage.HalMessage(m_type = "add to ui",
                                                   data = self.configure_dict))
                
            self.sendMessage(halMessage.HalMessage(m_type = "initial parameters",
                                                   data = {"parameters" : self.view.getParameters()}))

            # Let the settings.settings module know that it needs
            # to wait for us during a parameter change.
            self.sendMessage(halMessage.HalMessage(m_type = "wait for",
                                                   data = {"module names" : ["settings"]}))

        elif message.isType("current parameters"):
            message.addResponse(halMessage.HalMessageResponse(source = self.module_name,
                                                              data = {"parameters" : self.view.getParameters().copy()}))

        elif message.isType("live mode") and message.sourceIs("testing"):
            self.view.setLiveMode(message.getData()["live mode"])

        elif message.isType("new parameters"):
            if self.locked_out:
                raise halExceptions.HalException("'new parameters' received while locked out.")
            message.addResponse(halMessage.HalMessageResponse(source = self.module_name,
                                                              data = {"old parameters" : self.view.getParameters().copy()}))
            # Update parameters.
            self.view.newParameters(message.getData()["parameters"].get(self.module_name))
            message.addResponse(halMessage.HalMessageResponse(source = self.module_name,
                                                              data = {"new parameters" : self.view.getParameters()}))


        elif message.isType("new shutters file"):
            self.view.setShutters(message.getData()["filename"])

        elif message.isType("ready to film"):
            self.waiting_on.remove(message.getSourceName())

            # All modules are ready, so start the cameras.
            if (len(self.waiting_on) == 0):
                self.startCameras()

        elif message.isType("start"):
            if self.view.amInLiveMode():
                self.startCameras()

        elif message.isType("start camera"):
            if self.locked_out and (message.getSource() != self):
                raise halExceptions.HalException("'start camera' received while locked out.")

        elif message.isType("start film request"):
            if self.locked_out:
                raise halExceptions.HalException("'start film request' received while locked out.")
            self.setLockout(True)
            film_settings = self.view.getFilmSettings(message.getData()["request"])
            if film_settings is not None:
                film_settings.setPixelSize(self.pixel_size)
                self.startFilmingLevel1(film_settings)
            else:
                self.setLockout(False)

        elif message.isType("stop camera"):
            if self.locked_out and (message.getSource() != self):
                raise halException.HalException("'stop camera' received while locked out.")

        elif message.isType("stop film"):
            message.addResponse(halMessage.HalMessageResponse(source = self.module_name,
                                                              data = {"parameters" : self.view.getParameters()}))

        elif message.isType("stop film request"):
            if (self.film_state != "run"):
                raise halExceptions.HalException("Stop film request received while not filming.")
            self.stopFilmingLevel1()

        elif message.isType("updated parameters"):
            self.parameter_change = True

        elif message.isType("wait for"):
            if self.module_name in message.getData()["module names"]:
                self.wait_for.append(message.getSourceName())
Пример #12
0
 def timeout(self, signum, frame):
     raise halExceptions.HalException("Job timed out!")