コード例 #1
0
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)

        self.have_stage = False
        self.is_classic = (module_params.get("ui_type") == "classic")
        self.parameters = module_params.get("parameters")
        self.qt_settings = qt_settings
        self.show_gui = True
        self.stage_functionality = None
        self.window_title = module_params.get("setup_name")
        
        self.viewers = []

        #
        # There is always at least one display by default.
        # This display provides a CameraFrameViewerFunctionality().
        #
        if self.is_classic:
            self.viewers.append(cameraViewers.ClassicViewer(module_name = self.getNextViewerName(),
                                                            default_colortable = self.parameters.get("colortable")))
        else:
            camera_viewer = cameraViewers.DetachedViewer(module_name = self.getNextViewerName(),
                                                         default_colortable = self.parameters.get("colortable"))
            camera_viewer.halDialogInit(self.qt_settings, self.window_title + " camera viewer")        
            self.viewers.append(camera_viewer)
        
        self.viewers[0].guiMessage.connect(self.handleGuiMessage)

        # This message comes from the shutter button.
        halMessage.addMessage("shutter clicked",
                              validator = {"data" : {"display_name" : [True, str],
                                                     "camera" : [True, str]},
                                           "resp" : None})
コード例 #2
0
    def __init__(self, module_params=None, qt_settings=None, **kwds):
        super().__init__(**kwds)
        self.control_action = None

        configuration = module_params.get("configuration")
        server = tcpServer.TCPServer(port=configuration.get("tcp_port"),
                                     server_name="Hal",
                                     parent=self)
        self.control = Controller(
            parallel_mode=configuration.get("parallel_mode"),
            server=server,
            parent=self)
        self.control.controlAction.connect(self.handleControlAction)
        self.control.controlMessage.connect(self.handleControlMessage)

        # TCP messages are packaged into this HAL message.
        #
        # The module(s) that handle the message need to add a 'handled' response
        # so that we know that someone did something with the message.
        #
        halMessage.addMessage("tcp message",
                              validator={
                                  "data": {
                                      "tcp message":
                                      [True, tcpMessage.TCPMessage]
                                  },
                                  "resp": {
                                      "handled": [True, bool]
                                  }
                              })
コード例 #3
0
ファイル: focusLock.py プロジェクト: BogdanBintu/MERFISH8
    def __init__(self, module_params=None, qt_settings=None, **kwds):
        super().__init__(**kwds)
        self.configuration = module_params.get("configuration")

        self.control = lockControl.LockControl(
            configuration=module_params.get("configuration"))
        self.view = FocusLockView(
            module_name=self.module_name,
            configuration=module_params.get("configuration"))
        self.view.halDialogInit(
            qt_settings,
            module_params.get("setup_name") + " focus lock")

        # Connect signals.
        self.control.controlMessage.connect(self.handleControlMessage)
        self.view.jump.connect(self.control.handleJump)
        self.view.lockStarted.connect(self.control.handleLockStarted)
        self.view.lockTarget.connect(self.control.handleLockTarget)
        self.view.modeChanged.connect(self.control.handleModeChanged)

        # This message is usually used by a USB joystick or Bluetooth control to
        # to request that the piezo stage move.
        halMessage.addMessage("lock jump",
                              validator={
                                  "data": {
                                      "delta": [True, float]
                                  },
                                  "resp": None
                              })
コード例 #4
0
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)

        self.have_stage = False
        self.is_classic = (module_params.get("ui_type") == "classic")
        self.parameters = module_params.get("parameters")
        self.qt_settings = qt_settings
        self.show_gui = True
        self.stage_functionality = None
        self.window_title = module_params.get("setup_name")
        
        self.viewers = []

        #
        # There is always at least one display by default.
        #
        if self.is_classic:
            self.viewers.append(cameraViewers.ClassicViewer(module_name = self.getNextViewerName(),
                                                            default_colortable = self.parameters.get("colortable")))
        else:
            camera_viewer = cameraViewers.DetachedViewer(module_name = self.getNextViewerName(),
                                                         default_colortable = self.parameters.get("colortable"))
            camera_viewer.halDialogInit(self.qt_settings, self.window_title + " camera viewer")        
            self.viewers.append(camera_viewer)
        
        self.viewers[0].guiMessage.connect(self.handleGuiMessage)

        # This message comes from the shutter button.
        halMessage.addMessage("shutter clicked",
                              validator = {"data" : {"display_name" : [True, str],
                                                     "camera" : [True, str]},
                                           "resp" : None})
コード例 #5
0
 def __init__(self, module_params = None, qt_settings = None, **kwds):
     super().__init__(**kwds)
     self.camera_names = []
     self.feed_controller = None
     self.feed_names = []
     
     # This message comes from the display.display when it creates a new
     # viewer.
     halMessage.addMessage("get feed names",
                           validator = {"data" : {"extra data" : [False, str]},
                                        "resp" : {"feed names" : [True, list]}})
コード例 #6
0
 def __init__(self, module_params = None, qt_settings = None, **kwds):
     super().__init__(**kwds)
     self.camera_names = []
     self.feed_controller = None
     self.feed_names = []
     
     # This message comes from the display.display when it creates a new
     # viewer.
     halMessage.addMessage("get feed names",
                           validator = {"data" : {"extra data" : [False, str]},
                                        "resp" : {"feed names" : [True, list]}})
コード例 #7
0
    def __init__(self, **kwds):
        super().__init__(**kwds)
        self.run_shutters = False

        # These are the waveforms to output during a film.
        self.analog_waveforms = []
        self.digital_waveforms = []
        
        self.oversampling = 0
        self.waveform_len = 0

        # The message for passing waveforms to a Daq module.
        #
        # FIXME: Replace with a configuration message?
        #
        halMessage.addMessage("daq waveforms",
                              validator = {"data" : {"waveforms" : [True, list]},
                                           "resp" : None})
コード例 #8
0
ファイル: daqModule.py プロジェクト: ZhuangLab/storm-control
    def __init__(self, **kwds):
        super().__init__(**kwds)
        self.run_shutters = False

        # These are the waveforms to output during a film.
        self.analog_waveforms = []
        self.digital_waveforms = []
        
        self.oversampling = 0
        self.waveform_len = 0

        # The message for passing waveforms to a Daq module.
        #
        # FIXME: Replace with a configuration message?
        #
        halMessage.addMessage("daq waveforms",
                              validator = {"data" : {"waveforms" : [True, list]},
                                           "resp" : None})
コード例 #9
0
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)
        self.control_action = None

        configuration = module_params.get("configuration")
        server = tcpServer.TCPServer(port = configuration.get("tcp_port"),
                                     server_name = "Hal",
                                     parent = self)
        self.control = Controller(parallel_mode = configuration.get("parallel_mode"),
                                  server = server,
                                  parent = self)
        self.control.controlAction.connect(self.handleControlAction)
        self.control.controlMessage.connect(self.handleControlMessage)

        # TCP messages are packaged into this HAL message.
        #
        # The module(s) that handle the message need to add a 'handled' response
        # so that we know that someone did something with the message.
        #
        halMessage.addMessage("tcp message",
                              validator = {"data" : {"tcp message" : [True, tcpMessage.TCPMessage]},
                                           "resp" : {"handled" : [True, bool]}})
コード例 #10
0
ファイル: focusLock.py プロジェクト: ZhuangLab/storm-control
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)
        self.configuration = module_params.get("configuration")

        self.control = lockControl.LockControl(configuration = module_params.get("configuration"))
        self.view = FocusLockView(module_name = self.module_name,
                                  configuration = module_params.get("configuration"))
        self.view.halDialogInit(qt_settings,
                                module_params.get("setup_name") + " focus lock")

        # Connect signals.
        self.control.controlMessage.connect(self.handleControlMessage)
        self.view.jump.connect(self.control.handleJump)
        self.view.lockStarted.connect(self.control.handleLockStarted)
        self.view.lockTarget.connect(self.control.handleLockTarget)
        self.view.modeChanged.connect(self.control.handleModeChanged)

        # This message is usually used by a USB joystick or Bluetooth control to
        # to request that the piezo stage move.
        halMessage.addMessage("lock jump",
                              validator = {"data" : {"delta" : [True, float]},
                                           "resp" : None})
コード例 #11
0
    def __init__(self, module_params=None, qt_settings=None, **kwds):
        super().__init__(**kwds)

        self.processed_messages = ["tss1", "tss2"]

        # Borrowed this one from testing.testing.
        halMessage.addMessage("tests done",
                              validator={
                                  "data": None,
                                  "resp": None
                              })

        halMessage.addMessage("tss1", validator={"data": None, "resp": None})

        halMessage.addMessage("tss2", validator={"data": None, "resp": None})

        halMessage.addMessage("tss3", validator={"data": None, "resp": None})
コード例 #12
0
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)

        self.processed_messages = ["tss1", "tss2"]

        # Borrowed this one from testing.testing.
        halMessage.addMessage("tests done",
                              validator = {"data" : None, "resp" : None})
                
        halMessage.addMessage("tss1",
                              validator = {"data" : None, "resp" : None})
        
        halMessage.addMessage("tss2",
                              validator = {"data" : None, "resp" : None})
        
        halMessage.addMessage("tss3",
                              validator = {"data" : None, "resp" : None})
コード例 #13
0
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)

        self.all_modules = None
        self.current_action = None
        self.test_actions = []

        # This message type is just a place holder.
        halMessage.addMessage("na",
                              validator = {"data" : None, "resp" : None})
        
        # This message is sent but does not do anything.
        halMessage.addMessage("noop",
                              validator = {"data" : None, "resp" : None})

        # This message is sent when all the tests finish. HAL should
        # close when it gets this message.
        halMessage.addMessage("tests done",
                              validator = {"data" : None, "resp" : None})
コード例 #14
0
ファイル: testing.py プロジェクト: nvladimus/storm-control
    def __init__(self, module_params=None, qt_settings=None, **kwds):
        super().__init__(**kwds)

        self.all_modules = None
        self.current_action = None
        self.test_actions = []

        # This message type is just a place holder.
        halMessage.addMessage("na", validator={"data": None, "resp": None})

        # This message is sent but does not do anything.
        halMessage.addMessage("noop", validator={"data": None, "resp": None})

        # This message is sent when all the tests finish. HAL should
        # close when it gets this message.
        halMessage.addMessage("tests done",
                              validator={
                                  "data": None,
                                  "resp": None
                              })
コード例 #15
0
ファイル: settings.py プロジェクト: BehnamAbaie/storm-control
    def __init__(self, module_params=None, qt_settings=None, **kwds):
        super().__init__(**kwds)
        self.locked_out = False
        self.wait_for = []
        self.waiting_on = []

        self.view = parametersBox.ParametersBox(module_params=module_params,
                                                qt_settings=qt_settings)
        self.view.editParameters.connect(self.handleEditParameters)
        self.view.newParameters.connect(self.handleNewParameters)

        p = params.StormXMLObject()
        p.set("parameters_file",
              os.path.join(module_params.get("directory"), "default.xml"))

        #
        # Add parameter to record whether or not these parameters have actually
        # been used (as opposed to just appearing in the list view).
        #
        # They should be initialized since this is what we are starting with..
        #
        p.add(
            params.ParameterSetBoolean(name="initialized",
                                       value=False,
                                       is_mutable=False,
                                       is_saved=False))

        self.view.addParameters(p, is_default=True)

        self.configure_dict = {
            "ui_order": 0,
            "ui_parent": "hal.containerWidget",
            "ui_widget": self.view
        }

        # This message marks the beginning and the end of the parameter change
        # life cycle.
        halMessage.addMessage("changing parameters",
                              validator={
                                  "data": {
                                      "changing": [True, bool]
                                  },
                                  "resp": None
                              })

        # Other modules should respond to this message with their current
        # parameters.
        halMessage.addMessage("current parameters",
                              validator={
                                  "data": None,
                                  "resp": {
                                      "parameters":
                                      [False, params.StormXMLObject]
                                  }
                              })

        # A request from another module for one of the sets of parameters.
        halMessage.addMessage("get parameters",
                              validator={
                                  "data": {
                                      "index or name": [True, (str, int)]
                                  },
                                  "resp": {
                                      "parameters":
                                      [False, params.StormXMLObject],
                                      "found": [True, bool]
                                  }
                              })

        # The current parameters have changed.
        #
        # Data includes a copy of the desired new parameters. Other modules
        # should at least check if the new parameters are okay. They may
        # defer actually re-configuring until they receive the
        # 'updated parameters' message.
        #
        # Other modules that respond should send two response:
        #  1. A response with a copy of their old parameter as "old parameters".
        #  2. A response with their updated parameters as "new parameters".
        #
        # The response is structured this way so that if an error occurs
        # during the parameter update we still have a record of the last
        # good state in "old parameters".
        #
        # Notes:
        #   1. We send a copy of the parameters in the listview, so if the
        #      module wants to it can just use these as the parameters without
        #      copying them again.
        #
        #   2. The 'old parameters' response should be a copy.
        #
        #   3. The 'new parameters' response does not need to be a copy.
        #
        halMessage.addMessage("new parameters",
                              validator={
                                  "data": {
                                      "parameters":
                                      [True, params.StormXMLObject],
                                      "is_edit": [True, bool]
                                  },
                                  "resp": {
                                      "new parameters":
                                      [False, params.StormXMLObject],
                                      "old parameters":
                                      [False, params.StormXMLObject]
                                  }
                              })

        # This comes from other modules that requested "wait for" at startup.
        #
        # Modules may respond with their new parameters here if they did not know
        # the final values for the parameters at 'new parameters'. At this point
        # however the modules cannot complain that the parameters they were given
        # were invalid, this has to be done at 'new parameters'.
        #
        halMessage.addMessage("parameters changed",
                              validator={
                                  "data": {
                                      "new parameters":
                                      [False, params.StormXMLObject]
                                  },
                                  "resp": None
                              })

        # A request from another module to set the current parameters.
        halMessage.addMessage("set parameters",
                              validator={
                                  "data": {
                                      "index or name": [True, (str, int)]
                                  },
                                  "resp": {
                                      "found": [True, bool],
                                      "current": [True, bool]
                                  }
                              })

        # The updated parameters.
        #
        # These are the updated values of parameters of all of the modules.
        # This is sent immediately after all of the modules respond to
        # the 'new parameters' message.
        #
        # The parameter change cycle won't actually complete till all the
        # modules that requested a wait send the "parameters changed" message.
        #
        halMessage.addMessage(
            "updated parameters",
            validator={"data": {
                "parameters": [True, params.StormXMLObject]
            }})
コード例 #16
0
ファイル: settings.py プロジェクト: ZhuangLab/storm-control
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)
        self.locked_out = False
        self.wait_for = []
        self.waiting_on = []

        self.view = parametersBox.ParametersBox(module_params = module_params,
                                                qt_settings = qt_settings)
        self.view.editParameters.connect(self.handleEditParameters)
        self.view.newParameters.connect(self.handleNewParameters)

        p = params.StormXMLObject()
        p.set("parameters_file", os.path.join(module_params.get("directory"), "default.xml"))
    
        #
        # Add parameter to record whether or not these parameters have actually
        # been used (as opposed to just appearing in the list view).
        #
        # They should be initialized since this is what we are starting with..
        #
        p.add(params.ParameterSetBoolean(name = "initialized",
                                         value = False,
                                         is_mutable = False,
                                         is_saved = False))

        self.view.addParameters(p, is_default = True)

        self.configure_dict = {"ui_order" : 0,
                               "ui_parent" : "hal.containerWidget",
                               "ui_widget" : self.view}

        # This message marks the beginning and the end of the parameter change
        # life cycle.
        halMessage.addMessage("changing parameters",
                              validator = {"data" : {"changing" : [True, bool]},
                                           "resp" : None})        

        # Other modules should respond to this message with their current
        # parameters.
        halMessage.addMessage("current parameters",
                              validator = {"data" : None,
                                           "resp" : {"parameters" : [False, params.StormXMLObject]}})
                              
        # A request from another module for one of the sets of parameters.
        halMessage.addMessage("get parameters",
                              validator = {"data" : {"index or name" : [True, (str, int)]},
                                           "resp" : {"parameters" : [False, params.StormXMLObject],
                                                     "found" : [True, bool]}})
        
        # The current parameters have changed.
        #
        # Data includes a copy of the desired new parameters. Other modules
        # should at least check if the new parameters are okay. They may
        # defer actually re-configuring until they receive the
        # 'updated parameters' message.
        #
        # Other modules that respond should send two response:
        #  1. A response with a copy of their old parameter as "old parameters".
        #  2. A response with their updated parameters as "new parameters".
        #
        # The response is structured this way so that if an error occurs
        # during the parameter update we still have a record of the last
        # good state in "old parameters".
        #
        # Notes:
        #   1. We send a copy of the parameters in the listview, so if the
        #      module wants to it can just use these as the parameters without
        #      copying them again.
        #
        #   2. The 'old parameters' response should be a copy.
        #
        #   3. The 'new parameters' response does not need to be a copy.
        #
        halMessage.addMessage("new parameters",
                              validator = {"data" : {"parameters" : [True, params.StormXMLObject],
                                                     "is_edit" : [True, bool]},
                                           "resp" : {"new parameters" : [False, params.StormXMLObject],
                                                     "old parameters" : [False, params.StormXMLObject]}})

        # This comes from other modules that requested "wait for" at startup.
        #
        # Modules may respond with their new parameters here if they did not know
        # the final values for the parameters at 'new parameters'. At this point
        # however the modules cannot complain that the parameters they were given
        # were invalid, this has to be done at 'new parameters'.
        #
        halMessage.addMessage("parameters changed",
                              validator = {"data" : {"new parameters" : [False, params.StormXMLObject]},
                                           "resp" : None})

        # A request from another module to set the current parameters.
        halMessage.addMessage("set parameters",
                              validator = {"data" : {"index or name" : [True, (str, int)]},
                                           "resp" : {"found" : [True, bool],
                                                     "current" : [True, bool]}})

        # The updated parameters.
        #
        # These are the updated values of parameters of all of the modules.
        # This is sent immediately after all of the modules respond to
        # the 'new parameters' message.
        #
        # The parameter change cycle won't actually complete till all the
        # modules that requested a wait send the "parameters changed" message.
        #
        halMessage.addMessage("updated parameters",
                              validator = {"data" : {"parameters" : [True, params.StormXMLObject]}})
コード例 #17
0
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)

        self.camera_functionalities = []
        self.feed_names = None
        self.film_settings = None
        self.film_state = "idle"
        self.locked_out = False
        self.number_frames = 0
        self.number_fn_requested = 0
        self.parameter_change = False
        self.pixel_size = 1.0
        self.timing_functionality = None
        self.wait_for = []
        self.waiting_on = []
        self.writers = None
        self.writers_stopped_timer = QtCore.QTimer(self)

        try:
            self.logfile_fp = open(module_params.get("directory") + "image_log.txt", "a")
        except FileNotFoundError:
            print(">> image_log.txt file not found")
            self.logfile_fp = None

        self.writers_stopped_timer.setSingleShot(True)
        self.writers_stopped_timer.setInterval(10)
        self.writers_stopped_timer.timeout.connect(self.stopFilmingLevel2)

        p = module_params.getp("parameters")
        p.add(params.ParameterStringDirectory("Current working directory",
                                              "directory",
                                              module_params.get("directory"),
                                              is_mutable = False,
                                              is_saved = False))
                
        self.view = FilmBox(parameters = p)
        self.view.liveModeChange.connect(self.handleLiveModeChange)

        self.configure_dict = {"ui_order" : 1,
                               "ui_parent" : "hal.containerWidget",
                               "ui_widget" : self.view}

        # Sent when filming is not possible/possible. While this is true we'll
        # throw an error if another modules attempts to start/stop a film
        # or a camera. This is also the marker for the beginning / end of the
        # the film cycle.
        halMessage.addMessage("film lockout",
                              validator = {"data" : {"locked out" : [True, bool],
                                                     "acquisition parameters" : [False, params.StormXMLObject]},
                                           "resp" : None})
        
        # In live mode the camera also runs between films.
        halMessage.addMessage("live mode",
                              validator = {"data" : {"live mode" : [True, bool]},
                                           "resp" : None})

        # This comes from other modules that added a "wait for" request
        # to the 'start film' message.
        halMessage.addMessage("ready to film",
                              validator = {"data" : None, "resp" : None})
        
        # Start cameras (master of slaved).
        halMessage.addMessage("start camera",
                              validator = {"data" : {"master" : [True, bool]},
                                           "resp" : None})

        # Start filming.
        #
        # Filming won't start until all the modules that have
        # requested a wait send a "ready to film" message.
        #
        halMessage.addMessage("start film",
                              validator = {"data" : {"film settings" : [True, filmSettings.FilmSettings]}})

        # Request to start filming, either from a record button or via TCP.
        halMessage.addMessage("start film request",
                              validator = {"data" : {"request" : [True, filmRequest.FilmRequest]},
                                           "resp" : None})

        # Stop a camera.
        halMessage.addMessage("stop camera",
                              validator = {"data" : {"master" : [True, bool]},
                                           "resp" : None})

        # Stop filming.
        halMessage.addMessage("stop film",
                              validator = {"data" : {"film settings" : [True, filmSettings.FilmSettings],
                                                     "number frames" : [True, int]},
                                           "resp" : {"parameters" : [False, params.StormXMLObject],
                                                     "acquisition" : [False, list]}})

        # Request to stop filming.
        halMessage.addMessage("stop film request",
                              validator = {"data" : None,
                                           "resp" : None})
コード例 #18
0
ファイル: film.py プロジェクト: ZhuangLab/storm-control
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)

        self.active_cameras = 0
        self.camera_functionalities = []
        self.feed_names = None
        self.film_settings = None
        self.film_state = "idle"
        self.locked_out = False
        self.number_frames = 0
        self.number_fn_requested = 0
        self.parameter_change = False
        self.pixel_size = 1.0
        self.timing_functionality = None
        self.wait_for = []
        self.waiting_on = []
        self.writers = None
        self.writers_stopped_timer = QtCore.QTimer(self)

        try:
            self.logfile_fp = open(module_params.get("directory") + "image_log.txt", "a")
        except FileNotFoundError:
            print(">> image_log.txt file not found")
            self.logfile_fp = None

        self.writers_stopped_timer.setSingleShot(True)
        self.writers_stopped_timer.setInterval(10)
        self.writers_stopped_timer.timeout.connect(self.stopFilmingLevel2)

        p = module_params.getp("parameters")
        p.add(params.ParameterStringDirectory("Current working directory",
                                              "directory",
                                              module_params.get("directory"),
                                              is_mutable = False,
                                              is_saved = False))
                
        self.view = FilmBox(parameters = p)
        self.view.liveModeChange.connect(self.handleLiveModeChange)

        self.configure_dict = {"ui_order" : 1,
                               "ui_parent" : "hal.containerWidget",
                               "ui_widget" : self.view}

        # Sent when filming is not possible/possible. While this is true we'll
        # throw an error if another modules attempts to start/stop a film
        # or a camera. This is also the marker for the beginning / end of the
        # the film cycle.
        halMessage.addMessage("film lockout",
                              validator = {"data" : {"locked out" : [True, bool],
                                                     "acquisition parameters" : [False, params.StormXMLObject]},
                                           "resp" : None})
        
        # In live mode the camera also runs between films.
        halMessage.addMessage("live mode",
                              validator = {"data" : {"live mode" : [True, bool]},
                                           "resp" : None})

        # This comes from other modules that added a "wait for" request
        # to the 'start film' message.
        halMessage.addMessage("ready to film",
                              validator = {"data" : None, "resp" : None})
        
        # Start a camera.
        halMessage.addMessage("start camera",
                              validator = {"data" : {"camera" : [True, str]},
                                           "resp" : None})

        # Start filming.
        #
        # Filming won't start until all the modules that have
        # requested a wait send a "ready to film" message.
        #
        halMessage.addMessage("start film",
                              validator = {"data" : {"film settings" : [True, filmSettings.FilmSettings]}})

        # Request to start filming, either from a record button or via TCP.
        halMessage.addMessage("start film request",
                              validator = {"data" : {"request" : [True, filmRequest.FilmRequest]},
                                           "resp" : None})

        # Stop a camera.
        halMessage.addMessage("stop camera",
                              validator = {"data" : {"camera" : [True, str]},
                                           "resp" : None})

        # Stop filming.
        halMessage.addMessage("stop film",
                              validator = {"data" : {"film settings" : [True, filmSettings.FilmSettings],
                                                     "number frames" : [True, int]},
                                           "resp" : {"parameters" : [False, params.StormXMLObject],
                                                     "acquisition" : [False, list]}})

        # Request to stop filming.
        halMessage.addMessage("stop film request",
                              validator = {"data" : None,
                                           "resp" : None})