Example #1
0
def test_parameters_8():
    s1 = params.StormXMLObject()
    s2 = params.StormXMLObject()
    p1 = params.Parameter(name="aa", order=2)
    p2 = params.Parameter(name="bb", order=1)
    p3 = params.Parameter(name="cc", order=2)

    s1.addSubSection("dd", s2)
    s1.add(p1)
    s1.add(p2)
    s1.add(p3)

    assert (s1.getSortedAttrs() == ['dd', 'bb', 'aa', 'cc'])
Example #2
0
    def __init__(self, configuration=None, **kwds):
        super().__init__(**kwds)
        self.buttons = []
        self.filter_fn = None
        self.parameters = params.StormXMLObject()
        self.scan_fn = None

        # Load UI
        self.ui = filterWheelUi.Ui_Dialog()
        self.ui.setupUi(self)

        # Create buttons.
        layout = QtWidgets.QHBoxLayout(self.ui.filtersGroupBox)
        layout.setContentsMargins(1, 1, 1, 1)
        layout.setSpacing(1)
        filter_names = configuration.get("filters").split(",")
        for name in filter_names:
            button = QtWidgets.QPushButton(name, self.ui.filtersGroupBox)
            button.setAutoExclusive(True)
            button.setCheckable(True)
            button.clicked.connect(self.handleClicked)
            layout.addWidget(button)
            self.buttons.append(button)

        # Set to minimum size & fix.
        self.adjustSize()
        self.setFixedSize(self.width(), self.height())

        self.parameters.add(
            params.ParameterSetString(description="Current filter",
                                      name="current_filter",
                                      value=filter_names[0],
                                      allowed=filter_names))
        self.setEnabled(False)
Example #3
0
def test_parameters_7():
    p1 = params.StormXMLObject()
    v1 = params.ParameterSimple("foo", "bar")
    p1.add(v1)

    p2 = params.StormXMLObject()
    p2.add("foo", p1.getp("foo"))

    p3 = params.StormXMLObject()
    p3.add("foo", p1.getp("foo").copy())

    v1.setv("baz")

    assert (p1.get("foo") == "baz")
    assert (p2.get("foo") == "baz")
    assert (p3.get("foo") == "bar")
Example #4
0
    def __init__(self, configuration = None, **kwds):
        """
        This initializes things and sets up the UI 
        of the power control dialog box.
        """
        super().__init__(**kwds)

        self.channels = False
        self.configuration = configuration
        self.directory = None
        self.exp_channels = None
        self.ilm_functionality = None
        self.linear_channels = None
        self.file_channels = None
        self.parameters = params.StormXMLObject()
        self.timing_functionality = None
        self.use_was_checked = False
        self.which_checked = []

        # Add progression parameters.
        self.parameters.add(params.ParameterSetBoolean(name = "use_progressions",
                                                       value = False,
                                                       is_mutable = False))
        
        self.parameters.add(params.ParameterStringFilename(description = "Progression file name",
                                                           name = "pfile_name",
                                                           value = "",
                                                           use_save_dialog = False))

        # UI setup
        self.ui = progressionUi.Ui_Dialog()
        self.ui.setupUi(self)

        self.ui.loadFileButton.clicked.connect(self.handleLoadFile)
        self.ui.progressionsCheckBox.stateChanged.connect(self.handleProgressionsCheck)
Example #5
0
    def __init__(self, configuration = None, **kwds):
        super().__init__(**kwds)
        self.parameters = params.StormXMLObject()
        self.retracted_z = configuration.get("retracted_z")
        self.z_stage_fn = None

        # Load UI
        self.ui = zStageUi.Ui_Dialog()
        self.ui.setupUi(self)

        self.ui.homeButton.clicked.connect(self.handleHomeButton)
        self.ui.retractButton.clicked.connect(self.handleRetractButton)
        self.ui.zeroButton.clicked.connect(self.handleZeroButton)
        self.ui.zPosDoubleSpinBox.valueChanged.connect(self.handleZValueChanged)

        self.setZStep(configuration.get("single_step"))
        
        # Set to minimum size & fix.
        self.adjustSize()
        self.setFixedSize(self.width(), self.height())

        # Add parameters.
        self.parameters.add(params.ParameterRangeFloat(description ="Z Stage step size",
                                                       name = "z_stage_step",
                                                       value = configuration.get("single_step"),
                                                       min_value = 0.001,
                                                       max_value = 1.0))
        
        self.setEnabled(False)
Example #6
0
    def __init__(self, module_params=None, qt_settings=None, **kwds):
        super().__init__(**kwds)
        self.analyzers = []
        self.basename = None
        self.feed_names = []
        self.number_fn_requested = 0
        self.pixel_size = 0.1
        self.shutters_info = None

        configuration = module_params.get("configuration")

        self.spot_counter = findSpots.SpotCounter(
            max_threads=configuration.get("max_threads"),
            max_size=configuration.get("max_size"))

        self.view = SpotCounterView(module_name=self.module_name,
                                    configuration=configuration)
        self.view.halDialogInit(
            qt_settings,
            module_params.get("setup_name") + " spot counter")

        # Spot counter parameters.
        self.parameters = params.StormXMLObject()

        self.parameters.add(
            params.ParameterRangeInt(
                description="Maximum counts for the spotcounter graph",
                name="max_spots",
                value=500,
                min_value=0,
                max_value=1000,
                is_mutable=False,
                is_saved=False))

        self.parameters.add(
            params.ParameterRangeFloat(description="Scale bar length in nm",
                                       name="scale_bar_len",
                                       value=2000,
                                       min_value=100,
                                       max_value=10000))

        self.parameters.add(
            params.ParameterRangeInt(
                description="Spot detection threshold (camera counts)",
                name="threshold",
                value=250,
                min_value=1,
                max_value=10000))

        self.parameters.add(
            params.ParameterString(description="Which camera to display.",
                                   name="which_camera",
                                   value="",
                                   is_mutable=False,
                                   is_saved=False))
Example #7
0
    def __init__(self, module_params = None, qt_settings = None, **kwds):
        super().__init__(**kwds)
        self.timing_functionality = None

        self.parameters = params.StormXMLObject()

        self.parameters.add(params.ParameterSetString(description = "Feed to use as the time base when filming",
                                                      name = "time_base",
                                                      value = "",
                                                      allowed = [""]))

        default_time_base = module_params.get("parameters").get("time_base")
        self.setAllowed([default_time_base])
        self.parameters.setv("time_base", default_time_base)
Example #8
0
    def __init__(self, configuration=None, **kwds):
        super().__init__(**kwds)
        self.parameters = params.StormXMLObject()
        self.retracted_z = configuration.get("retracted_z")
        self.z_stage_fn = None

        # Load UI
        self.ui = zStageUi.Ui_Dialog()
        self.ui.setupUi(self)

        icon_path = os.path.join(os.path.dirname(__file__), "../icons/")
        self.ui.upLButton.setIcon(
            QtGui.QIcon(os.path.join(icon_path, "2uparrow-128.png")))
        self.ui.upLButton.clicked.connect(self.handleUpLButton)
        self.ui.upSButton.setIcon(
            QtGui.QIcon(os.path.join(icon_path, "1uparrow-128.png")))
        self.ui.upSButton.clicked.connect(self.handleUpSButton)
        self.ui.downSButton.setIcon(
            QtGui.QIcon(os.path.join(icon_path, "1downarrow-128.png")))
        self.ui.downSButton.clicked.connect(self.handleDownSButton)
        self.ui.downLButton.setIcon(
            QtGui.QIcon(os.path.join(icon_path, "2downarrow-128.png")))
        self.ui.downLButton.clicked.connect(self.handleDownLButton)

        self.ui.homeButton.clicked.connect(self.handleHomeButton)
        self.ui.retractButton.clicked.connect(self.handleRetractButton)
        self.ui.zeroButton.clicked.connect(self.handleZeroButton)

        self.ui.goButton.clicked.connect(self.handleGoButton)

        # Set to minimum size & fix.
        self.adjustSize()
        self.setFixedSize(self.width(), self.height())

        # Add parameters.
        self.parameters.add(
            params.ParameterRangeFloat(description="Z Stage large step size",
                                       name="z_large_step",
                                       value=configuration.get("large_step"),
                                       min_value=0.001,
                                       max_value=100.0))
        self.parameters.add(
            params.ParameterRangeFloat(description="Z Stage small step size",
                                       name="z_small_step",
                                       value=configuration.get("small_step"),
                                       min_value=0.001,
                                       max_value=10.0))

        self.setEnabled(False)
Example #9
0
def test_parameters_6():
    p1 = params.StormXMLObject()

    s1 = p1.addSubSection("foo")
    s1.add("bar1", "foo1")

    s2 = p1.addSubSection("foo.bar")
    s2.add("bar2", "foo2")

    s3 = p1.addSubSection("bar.foo")
    s3.add("foo1", "bar1")

    assert (p1.get("foo.bar1") == "foo1")
    assert (p1.get("foo.bar.bar2") == "foo2")
    assert (p1.get("bar.foo.foo1") == "bar1")
Example #10
0
    def __init__(self, configuration=None, **kwds):
        super().__init__(**kwds)
        self.current_mode = None
        self.modes = []
        self.parameters = params.StormXMLObject()

        self.ui = focuslockUi.Ui_Dialog()
        self.ui.setupUi(self)

        # Add parameters
        self.parameters.add(
            params.ParameterFloat(description="Z stage jump size",
                                  name="jump_size",
                                  value=0.1))

        # Set up lock display.
        self.lock_display = lockDisplay.LockDisplay(
            configuration=configuration, jump_signal=self.jump, parent=self)
        layout = QtWidgets.QGridLayout(self.ui.lockDisplayWidget)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.lock_display)

        # Configure modes.
        lockModes.FindSumMixin.addParameters(self.parameters)
        lockModes.LockedMixin.addParameters(self.parameters)
        lockModes.ScanMixin.addParameters(self.parameters)
        for mode_class_name in configuration.get("lock_modes").split(","):
            a_class = getattr(lockModes, mode_class_name.strip())
            a_object = a_class(parameters=self.parameters, parent=self)
            self.ui.modeComboBox.addItem(a_object.getName())
            self.modes.append(a_object)

        # Set parameters values based on the config file parameters.
        c_params = configuration.get("parameters")
        for attr in params.difference(c_params, self.parameters):
            print(attr, c_params.get(attr))
            self.parameters.setv(attr, c_params.get(attr))
        self.newParameters(self.parameters)

        # Connect signals.
        self.ui.jumpNButton.clicked.connect(self.handleJumpNButton)
        self.ui.jumpPButton.clicked.connect(self.handleJumpPButton)
        self.ui.lockButton.clicked.connect(self.handleLockButton)
        self.ui.lockTargetSpinBox.valueChanged.connect(self.handleLockTarget)
        self.ui.modeComboBox.currentIndexChanged.connect(
            self.handleModeComboBox)

        self.setEnabled(False)
Example #11
0
def test_parameters_3():

    # Load parameters.
    p1 = params.parameters(test.xmlFilePathAndName("test_parameters.xml"),
                           recurse=True)

    # Test sub-section creation.
    p2 = params.StormXMLObject()
    p2s = p2.addSubSection("camera1", p1.get("camera1").copy())
    p2s.add(params.ParameterInt(name="test", value=5))

    # p2 is different then p1 because it has 'test'.
    assert (params.difference(p2.get("camera1"),
                              p1.get("camera1"))[0] == "test")

    # But p1 is not different from p2 because difference() only
    # checks p1 properties that exist in p1.
    assert (len(params.difference(p1.get("camera1"), p2.get("camera1"))) == 0)
Example #12
0
    def __init__(self, module_params=None, qt_settings=None, **kwds):
        super().__init__(**kwds)
        self.film_settings = None
        self.hardware_timing_functionality = None

        self.configuration = module_params.get("configuration")

        self.parameters = params.StormXMLObject()

        #
        # FIXME: The range would be better set by what the cameras allow
        #        based on their current configuration.
        #
        self.parameters.add(
            params.ParameterRangeFloat(
                description="Frames per second",
                name="fps",
                value=self.configuration.get("fps", 0.1),
                min_value=self.configuration.get("fps_min", 0.001),
                max_value=self.configuration.get("fps_max", 10000.0)))
Example #13
0
def test_parameters_4():

    # Load parameters.
    p1 = params.parameters(test.xmlFilePathAndName("test_parameters.xml"),
                           recurse=True)

    # Create another set of parameters with only 1 item.
    p2 = params.StormXMLObject()
    p2.add(params.ParameterString(name="test_param", value="bar"))
    p2s = p2.addSubSection("camera1")
    p2s.add(params.ParameterSetBoolean(name="flip_horizontal", value=True))
    p2s.add(params.ParameterSetBoolean(name="flip_vertical", value=False))

    # Test copy.
    [p3, ur] = params.copyParameters(p1, p2)

    # Their should be one un-recognized parameter, 'flip_vertical'.
    assert (len(ur) == 1) and (ur[0] == "flip_vertical")

    # 'camera1.flip_horizontal' in p3 should be True.
    assert p3.get("camera1.flip_horizontal")

    # 'test_param' should be 'bar'.
    assert (p3.get("test_param") == "bar")
Example #14
0
    def __init__(self, configuration=None, **kwds):
        super().__init__(**kwds)

        self.channel_name_to_id = {}
        self.channels = []
        self.channels_by_name = {}
        self.parameters = params.StormXMLObject()
        self.power_fp = None
        self.running_shutters = False
        self.shutters_info = False
        self.timing_functionality = None
        self.waveforms = []
        self.xml_directory = os.path.dirname(os.path.dirname(__file__))

        # UI setup.
        self.ui = illuminationUi.Ui_Dialog()
        self.ui.setupUi(self)

        number_channels = len(configuration.getAttrs())

        # Default power setting.
        #
        # FIXME: This assumes that all the channels are normalized
        #        so that the maximum power is 1.0.
        #
        default_power = []
        for i in range(number_channels):
            default_power.append(1.0)
        self.parameters.add(
            illuminationParameters.ParameterDefaultPowers(description="Power",
                                                          name="default_power",
                                                          value=default_power,
                                                          is_mutable=False))

        # Default on/off state.
        on_off_state = []
        for i in range(number_channels):
            on_off_state.append(False)
        self.parameters.add(
            illuminationParameters.ParameterOnOffStates(description="On/Off",
                                                        name="on_off_state",
                                                        value=on_off_state,
                                                        is_mutable=False))

        # Default buttons.
        buttons = []
        for i in range(number_channels):
            buttons.append([["Max", 1.0], ["Low", 0.1]])
        self.parameters.add(
            illuminationParameters.ParameterPowerButtons(description="Buttons",
                                                         name="power_buttons",
                                                         value=buttons))

        # Default shutters file.
        filename = os.path.join(self.xml_directory, "shutters_default.xml")
        self.parameters.add(
            params.ParameterStringFilename(description="Shutters file name",
                                           name="shutters",
                                           value=filename,
                                           use_save_dialog=False))

        # Illumination channels setup.
        layout = QtWidgets.QHBoxLayout(self.ui.powerControlBox)
        layout.setContentsMargins(1, 1, 1, 1)
        layout.setSpacing(1)
        for i, cname in enumerate(sorted(configuration.getAttrs())):
            a_instance = illuminationChannel.Channel(
                channel_id=i,
                configuration=configuration.get(cname),
                parent=self.ui.powerControlBox)
            self.channel_name_to_id[a_instance.getName()] = i
            self.channels.append(a_instance)
            self.channels_by_name[a_instance.getName()] = a_instance
            layout.addWidget(a_instance.channel_ui)
Example #15
0
    def __init__(self, w1=None, configuration=None, **kwds):
        super().__init__(**kwds)
        self.w1 = w1

        # Query W1 for it's maximum speed.
        max_speed = self.w1.commandResponse("MS_MAX,?")
        assert max_speed is not None

        # Create dictionaries for the configuration of the
        # filter wheels and two dichroic mirror sets.
        self.filter_wheel_1_config = {}
        values = configuration.get("filter_wheel_1")
        filter_names = values.split(",")
        for pos, filter_name in enumerate(filter_names):
            self.filter_wheel_1_config[filter_name] = pos + 1

        self.filter_wheel_2_config = {}
        values = configuration.get("filter_wheel_2")
        filter_names = values.split(",")
        for pos, filter_name in enumerate(filter_names):
            self.filter_wheel_2_config[filter_name] = pos + 1

        self.dichroic_mirror_config = {}
        values = configuration.get("dichroic_mirror")
        dichroic_names = values.split(",")
        for pos, dichroic_name in enumerate(dichroic_names):
            self.dichroic_mirror_config[dichroic_name] = pos + 1

        self.camera_dichroic_config = {}
        values = configuration.get("camera_dichroic")
        camera_dichroic_names = values.split(",")
        for pos, camera_dichroic in enumerate(camera_dichroic_names):
            self.camera_dichroic_config[camera_dichroic] = pos + 1

        # Create parameters
        self.parameters = params.StormXMLObject()

        self.parameters.add(
            params.ParameterSetBoolean(
                description="Bypass spinning disk for brightfield mode?",
                name="bright_field_bypass",
                value=False))

        self.parameters.add(
            params.ParameterSetBoolean(description="Spin the disk?",
                                       name="spin_disk",
                                       value=True))

        # Disk properties
        self.parameters.add(
            params.ParameterSetString(
                description="Disk pinhole size",
                name="disk",
                value="50-micron pinholes",
                allowed=["50-micron pinholes", "25-micron pinholes"]))

        self.parameters.add(
            params.ParameterRangeInt(description="Disk speed (RPM)",
                                     name="disk_speed",
                                     value=max_speed,
                                     min_value=1,
                                     max_value=max_speed))

        # Dichroic mirror position
        values = sorted(self.dichroic_mirror_config.keys())
        self.parameters.add(
            params.ParameterSetString(description="Dichroic mirror position",
                                      name="dichroic_mirror",
                                      value=values[0],
                                      allowed=values))

        # Filter wheel positions
        values = sorted(self.filter_wheel_1_config.keys())
        self.parameters.add(
            params.ParameterSetString(
                description="Camera 1 Filter Wheel Position (1-10)",
                name="filter_wheel_pos1",
                value=values[0],
                allowed=values))

        values = sorted(self.filter_wheel_2_config.keys())
        self.parameters.add(
            params.ParameterSetString(
                description="Camera 2 Filter Wheel Position (1-10)",
                name="filter_wheel_pos2",
                value=values[0],
                allowed=values))

        # Camera dichroic positions
        values = sorted(self.camera_dichroic_config.keys())
        self.parameters.add(
            params.ParameterSetString(
                description="Camera dichroic mirror position (1-3)",
                name="camera_dichroic_mirror",
                value=values[0],
                allowed=values))

        # Aperature settings
        self.parameters.add(
            params.ParameterRangeInt(
                description="Aperture value (1-10; small to large)",
                name="aperture",
                value=10,
                min_value=1,
                max_value=10))

        self.newParameters(self.parameters, initialization=True)
Example #16
0
    def __init__(self, **kwds):
        super().__init__(**kwds)
        self.directory = ""
        self.parameters = params.StormXMLObject()
        self.stage_functionality = None

        # Add stage UI parameters.
        self.parameters.add(
            params.ParameterRangeFloat(description="Large step size (microns)",
                                       name="large_step_size",
                                       value=200.0,
                                       min_value=1.0,
                                       max_value=1000.0))

        self.parameters.add(
            params.ParameterRangeFloat(description="Small step size (microns)",
                                       name="small_step_size",
                                       value=10.0,
                                       min_value=1.0,
                                       max_value=100.0))

        # UI setup.
        self.ui = stageUi.Ui_Dialog()
        self.ui.setupUi(self)

        # Configure all the stage movement buttons.
        icon_path = os.path.join(os.path.dirname(__file__), "../icons/")
        self.motion_buttons = [
            MotionButton(button=self.ui.leftSButton,
                         icon=os.path.join(icon_path, "1leftarrow-128.png"),
                         button_type="small",
                         xval=1,
                         yval=0),
            MotionButton(button=self.ui.leftLButton,
                         icon=os.path.join(icon_path, "2leftarrow-128.png"),
                         button_type="large",
                         xval=1,
                         yval=0),
            MotionButton(button=self.ui.rightSButton,
                         icon=os.path.join(icon_path, "1rightarrow-128.png"),
                         button_type="small",
                         xval=-1,
                         yval=0),
            MotionButton(button=self.ui.rightLButton,
                         icon=os.path.join(icon_path, "2rightarrow-128.png"),
                         button_type="large",
                         xval=-1,
                         yval=0),
            MotionButton(button=self.ui.upSButton,
                         icon=os.path.join(icon_path, "1uparrow-128.png"),
                         button_type="small",
                         xval=0,
                         yval=1),
            MotionButton(button=self.ui.upLButton,
                         icon=os.path.join(icon_path, "2uparrow-128.png"),
                         button_type="large",
                         xval=0,
                         yval=1),
            MotionButton(button=self.ui.downSButton,
                         icon=os.path.join(icon_path, "1downarrow-128.png"),
                         button_type="small",
                         xval=0,
                         yval=-1),
            MotionButton(button=self.ui.downLButton,
                         icon=os.path.join(icon_path, "2downarrow-128.png"),
                         button_type="large",
                         xval=0,
                         yval=-1)
        ]
        for button in self.motion_buttons:
            button.motionClicked.connect(self.handleMotionClicked)

        # Connect the rest of the UI elements.
        self.ui.addButton.clicked.connect(self.handleAddButton)
        self.ui.clearButton.clicked.connect(self.handleClearButton)
        self.ui.goButton.clicked.connect(self.handleGoButton)
        self.ui.homeButton.clicked.connect(self.handleHomeButton)
        self.ui.loadButton.clicked.connect(self.handleLoadButton)
        self.ui.saveButton.clicked.connect(self.handleSaveButton)
        self.ui.saveComboBox.activated.connect(self.handleSaveComboBox)
        self.ui.zeroButton.clicked.connect(self.handleZeroButton)

        self.newParameters(self.parameters)

        # Disable UI until we get a stage functionality.
        self.setEnabled(False)
Example #17
0
    def __init__(self, camera_name=None, config=None, **kwds):
        """
        camera_name - This is the name of this camera's section in the config XML file.        
        config - These are the values in the parameters section as a StormXMLObject().
        """
        super().__init__(**kwds)

        # This is the hardware module that will actually control the camera.
        self.camera = None

        # Sub-classes should set this to a CameraFunctionality object.
        self.camera_functionality = None

        self.camera_name = camera_name

        # This is a flag for whether or not the camera is in a working state.
        # It might not be if for example the parameters were bad.
        self.camera_working = True

        # The length of a fixed length film.
        self.film_length = None

        # The current frame number, this gets reset by startCamera().
        self.frame_number = 0

        # The camera parameters.
        self.parameters = params.StormXMLObject()

        # This is how we tell the thread that is handling actually talking
        # to the camera hardware to stop.
        self.running = False

        # This is how we know that the camera thread that is talking to the
        # camera actually started.
        self.thread_started = False

        #
        # These are the minimal parameters that every camera must provide
        # to work with HAL.
        #

        # The exposure time.
        self.parameters.add(
            params.ParameterFloat(description="Exposure time (seconds)",
                                  name="exposure_time",
                                  value=1.0))

        # This is frames per second as reported by the camera. It is used
        # for hardware timed waveforms (if any).
        self.parameters.add(
            params.ParameterFloat(name="fps", value=0, is_mutable=False))

        #
        # Chip size, ROI of the chip and the well depth.
        #
        x_size = 256
        y_size = 256
        self.parameters.add(
            params.ParameterInt(name="x_chip",
                                value=x_size,
                                is_mutable=False,
                                is_saved=False))

        self.parameters.add(
            params.ParameterInt(name="y_chip",
                                value=y_size,
                                is_mutable=False,
                                is_saved=False))

        self.parameters.add(
            params.ParameterInt(name="max_intensity",
                                value=128,
                                is_mutable=False,
                                is_saved=False))

        #
        # Note: These are all expected to be in units of binned pixels. For
        # example if the camera is 512 x 512 and we are binning by 2s then
        # the maximum value of these would 256 x 256.
        #
        self.parameters.add(
            params.ParameterRangeInt(description="AOI X start",
                                     name="x_start",
                                     value=1,
                                     min_value=1,
                                     max_value=x_size))

        self.parameters.add(
            params.ParameterRangeInt(description="AOI X end",
                                     name="x_end",
                                     value=x_size,
                                     min_value=1,
                                     max_value=x_size))

        self.parameters.add(
            params.ParameterRangeInt(description="AOI Y start",
                                     name="y_start",
                                     value=1,
                                     min_value=1,
                                     max_value=y_size))

        self.parameters.add(
            params.ParameterRangeInt(description="AOI Y end",
                                     name="y_end",
                                     value=y_size,
                                     min_value=1,
                                     max_value=y_size))

        self.parameters.add(
            params.ParameterInt(name="x_pixels", value=0, is_mutable=False))

        self.parameters.add(
            params.ParameterInt(name="y_pixels", value=0, is_mutable=False))

        self.parameters.add(
            params.ParameterRangeInt(description="Binning in X",
                                     name="x_bin",
                                     value=1,
                                     min_value=1,
                                     max_value=4))

        self.parameters.add(
            params.ParameterRangeInt(description="Binning in Y",
                                     name="y_bin",
                                     value=1,
                                     min_value=1,
                                     max_value=4))

        # Frame size in bytes.
        self.parameters.add(
            params.ParameterInt(name="bytes_per_frame",
                                value=x_size * y_size * 2,
                                is_mutable=False,
                                is_saved=False))

        #
        # How/if data from this camera is saved.
        #
        self.parameters.add(
            params.ParameterString(
                description="Camera save filename extension",
                name="extension",
                value=""))

        self.parameters.add(
            params.ParameterSetBoolean(
                description="Save data from this camera when filming",
                name="saved",
                value=True))

        self.parameters.set("extension", config.get("extension", ""))
        self.parameters.set("saved", config.get("saved", True))

        #
        # Camera display orientation. Values can only be changed by
        # changing the config.xml file.
        #
        self.parameters.add(
            params.ParameterSetBoolean(name="flip_horizontal",
                                       value=False,
                                       is_mutable=False))

        self.parameters.add(
            params.ParameterSetBoolean(name="flip_vertical",
                                       value=False,
                                       is_mutable=False))

        self.parameters.add(
            params.ParameterSetBoolean(name="transpose",
                                       value=False,
                                       is_mutable=False))

        self.parameters.set("flip_horizontal",
                            config.get("flip_horizontal", False))
        self.parameters.set("flip_vertical",
                            config.get("flip_vertical", False))
        self.parameters.set("transpose", config.get("transpose", False))

        #
        # Camera default display minimum and maximum.
        #
        # These are the values the display will use by default. They can
        # only be changed by changing the config.xml file.
        #
        self.parameters.add(
            params.ParameterInt(name="default_max",
                                value=2000,
                                is_mutable=False))

        self.parameters.add(
            params.ParameterInt(name="default_min",
                                value=100,
                                is_mutable=False))

        self.parameters.set("default_max", config.get("default_max", 2000))
        self.parameters.set("default_min", config.get("default_min", 100))

        self.finished.connect(self.handleFinished)
        self.newData.connect(self.handleNewData)
Example #18
0
    def __init__(self, display_name = None, feed_name = "camera1", default_colortable = None, **kwds):
        super().__init__(**kwds)

        # General (alphabetically ordered).
        self.cam_fn = None
        self.cfv_functionality = CameraFrameViewerFunctionality()
        self.color_gradient = None
        self.color_tables = colorTables.ColorTables(os.path.dirname(__file__) + "/../colorTables/all_tables/")
        self.cycle_length = 0
        self.default_colortable = default_colortable
        self.default_parameters = params.StormXMLObject(validate = False) 
        self.display_name = display_name
        self.display_timer = QtCore.QTimer(self)
        self.filming = False
        self.frame = False
        self.parameters = False
        self.rubber_band_rect = None
        self.show_grid = False
        self.show_info = True
        self.show_target = False
        self.stage_functionality = None

        #
        # Keep track of the default feed_name in the default parameters, these
        # are the parameters that will be used when we change parameter files
        # and the parameters file doesn't specify anything for this view.
        #
        self.default_parameters.add(params.ParameterString(name = "feed_name",
                                                           value = feed_name,
                                                           is_mutable = False))

        # Set current parameters to default parameters.
        self.parameters = self.default_parameters.copy()
        
        # UI setup.
        self.ui = cameraDisplayUi.Ui_Frame()
        self.ui.setupUi(self)

        # Camera frame display.
        self.camera_view = self.ui.cameraGraphicsView
        self.camera_scene = qtCameraGraphicsScene.QtCameraGraphicsScene(parent = self)
        self.camera_widget = qtCameraGraphicsScene.QtCameraGraphicsItem()
        
        self.camera_scene.addItem(self.camera_widget)
        self.camera_view.setScene(self.camera_scene)
        self.camera_view.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(0,0,0)))
        
        # Display range slider.
        self.ui.rangeSlider = qtRangeSlider.QVRangeSlider()
        layout = QtWidgets.QGridLayout(self.ui.rangeSliderWidget)
        layout.setContentsMargins(1,1,1,1)
        layout.addWidget(self.ui.rangeSlider)
        self.ui.rangeSliderWidget.setLayout(layout)
        self.ui.rangeSlider.setEmitWhileMoving(True)

        # Color tables combo box.
        for color_name in sorted(self.color_tables.getColorTableNames()):
            self.ui.colorComboBox.addItem(color_name[:-5])

        self.ui.gridAct = QtWidgets.QAction(self.tr("Show Grid"), self)
        self.ui.infoAct = QtWidgets.QAction(self.tr("Hide Info"), self)
        self.ui.targetAct = QtWidgets.QAction(self.tr("Show Target"), self)

        # The default is not to show the shutter or the record button.
        self.ui.recordButton.hide()
        self.ui.shutterButton.hide()

        # These are always hidden unless we are filming.
        self.ui.syncLabel.hide()
        self.ui.syncSpinBox.hide()

        # FIXME: This only sort of works, the text is still getting cut-off.
        self.ui.feedComboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
        
        # Connect signals.
        self.camera_view.horizontalScrollBar().sliderReleased.connect(self.handleScrollBar)
        self.camera_view.newCenter.connect(self.handleNewCenter)
        self.camera_view.newScale.connect(self.handleNewScale)
        self.camera_view.verticalScrollBar().sliderReleased.connect(self.handleScrollBar)

        self.camera_view.dragMove.connect(self.handleDragMove)
        self.camera_view.dragStart.connect(self.handleDragStart)
        self.camera_view.rubberBandChanged.connect(self.handleRubberBandChanged)

        self.ui.autoScaleButton.clicked.connect(self.handleAutoScale)
        self.ui.colorComboBox.currentIndexChanged[str].connect(self.handleColorTableChange)
        self.ui.feedComboBox.currentIndexChanged[str].connect(self.handleFeedChange)
        self.ui.gridAct.triggered.connect(self.handleGrid)
        self.ui.infoAct.triggered.connect(self.handleInfo)        
        self.ui.rangeSlider.doubleClick.connect(self.handleAutoScale)        
        self.ui.rangeSlider.rangeChanged.connect(self.handleRangeChange)
        self.ui.syncSpinBox.valueChanged.connect(self.handleSync)
        self.ui.targetAct.triggered.connect(self.handleTarget)

        # Display timer, the display updates at approximately 10Hz.
        self.display_timer.setInterval(100)
        self.display_timer.timeout.connect(self.handleDisplayTimer)
        self.display_timer.start()
Example #19
0
    def __init__(self, joystick=None, joystick_gains=None, **kwds):
        super().__init__(**kwds)

        self.button_timer = QtCore.QTimer(self)
        self.joystick = joystick
        self.joystick_gains = joystick_gains  # XML should be [25.0, 250.0, 2500.0]
        self.old_right_joystick = [0, 0]
        self.old_left_joystick = [0, 0]
        self.stage_functionality = None
        self.to_emit = False

        # The joystick parameters.
        self.parameters = params.StormXMLObject()

        self.parameters.add(
            params.ParameterInt(name="joystick_gain_index",
                                value=0,
                                is_mutable=False,
                                is_saved=False))

        self.parameters.add(
            params.ParameterInt(name="multiplier",
                                value=1,
                                is_mutable=False,
                                is_saved=False))

        self.parameters.add(
            params.ParameterRangeFloat(
                description="Step size in um for hat button press",
                name="hat_step",
                value=1.0,
                min_value=0.0,
                max_value=10.0))

        self.parameters.add(
            params.ParameterRangeFloat(
                description="X button multiplier for joystick and focus lock",
                name="joystick_multiplier_value",
                value=5.0,
                min_value=0.0,
                max_value=50.0))

        self.parameters.add(
            params.ParameterSetString(description="Response mode",
                                      name="joystick_mode",
                                      value="quadratic",
                                      allowed=["linear", "quadratic"]))

        self.parameters.add(
            params.ParameterSetFloat(description="Sign for x motion",
                                     name="joystick_signx",
                                     value=1.0,
                                     allowed=[-1.0, 1.0]))

        self.parameters.add(
            params.ParameterSetFloat(description="Sign for y motion",
                                     name="joystick_signy",
                                     value=1.0,
                                     allowed=[-1.0, 1.0]))

        self.parameters.add(
            params.ParameterRangeFloat(
                description="Focus lock step size in um",
                name="lockt_step",
                value=0.025,
                min_value=0.0,
                max_value=1.0))

        self.parameters.add(
            params.ParameterRangeFloat(
                description="Minimum joystick offset to be non-zero",
                name="min_offset",
                value=0.1,
                min_value=0.0,
                max_value=1.0))

        self.parameters.add(
            params.ParameterSetBoolean(description="Swap x and y axises",
                                       name="xy_swap",
                                       value=False))

        self.joystick.start(self.joystickHandler)

        self.button_timer.setInterval(100)
        self.button_timer.setSingleShot(True)
        self.button_timer.timeout.connect(self.buttonDownHandler)
Example #20
0
    def __init__(self, config = None, **kwds):
        super().__init__(**kwds)

        self.cfv_fn = None
        self.click_step = 1.0
        self.click_timer = QtCore.QTimer(self)
        self.click_x = 0.0
        self.click_y = 0.0
        self.client_sock = False
        self.connected = False
        self.default_image = QtGui.QImage("bt_image.png")
        self.drag_gain = 1.0
        self.drag_x = 0.0
        self.drag_y = 0.0
        self.filming = False
        self.image_is_new = True
        self.images_sent = 0
        self.is_down = False
        self.is_drag = False
        self.messages = []
        self.mutex = QtCore.QMutex()
        self.offset_min = None
        self.offset_max = None
        self.parameters = params.StormXMLObject()
        self.qpd_fn = None
        self.running = False
        self.send_pictures = config.get("send_pictures")
        self.show_camera = True
        self.stage_fn = None
        self.start_time = 0
        self.sum_min = None
        self.sum_max = None

        self.parameters.add(params.ParameterRangeFloat(description = "Drag multiplier",
                                                       name = "d_mult",
                                                       value = 100.0,
                                                       min_value = 0.1,
                                                       max_value = 1000.0))
                                                       
        self.parameters.add(params.ParameterRangeFloat(description = "Z step size in um",
                                                       name = "z_step",
                                                       value = 0.1,
                                                       min_value = 0.0,
                                                       max_value = 5.0))

        # Set current image to default.
        self.current_image = self.default_image

        # Setup bluetooth socket.
        have_bluetooth = True
        try:
            self.server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
            self.server_sock.bind(("",bluetooth.PORT_ANY))
            self.server_sock.listen(1)
            
            port = self.server_sock.getsockname()[1]
            print("Bluetooth: Listening on RFCOMM channel {0:d}".format(port))

            uuid = "3e1f9ea8-9c11-11e3-b248-425861b86ab6"
            
            bluetooth.advertise_service(self.server_sock, "halServer",
                                        service_id = uuid,
                                        service_classes = [uuid, bluetooth.SERIAL_PORT_CLASS],
                                        profiles = [bluetooth.SERIAL_PORT_PROFILE])
            
        except bluetooth.btcommon.BluetoothError:
            print(traceback.format_exc())
            print("Failed to start Bluetooth")
            have_bluetooth = False

        if have_bluetooth:

            # Setup timer.
            self.click_timer.setInterval(200)
            self.click_timer.timeout.connect(self.handleClickTimer)
            self.click_timer.setSingleShot(True)

            # Connect signals.
            self.newMessage.connect(self.handleNewMessage)
            self.start(QtCore.QThread.NormalPriority)
Example #21
0
    def handleResponses(self, message):

        if message.isType("get functionality"):
            assert (len(message.getResponses()) == 1)
            for response in message.getResponses():
                self.camera_functionalities.append(response.getData()["functionality"])
                self.number_fn_requested -= 1

            # And we are done with the parameter change.
            if self.parameter_change and (self.number_fn_requested == 0):
                self.parameter_change = False
                self.sendMessage(halMessage.HalMessage(m_type = "parameters changed"))

        # Modules that need additional time to get ready to film should
        # specify at start up that they need to be waited for.
        elif message.isType("start film"):

            # No modules requested waits, so start now.
            if (len(self.wait_for) == 0):
                self.startCameras()
        
        # Modules are expected to add their current parameters as responses
        # to the 'stop film' message. We save them in an xml file here.
        elif message.isType("stop film"):
            self.film_state = "idle"
            acq_p = None
            notes = ""
            film_settings = message.getData()["film settings"]
            number_frames = message.getData()["number frames"]
            if film_settings.isSaved():
                to_save = params.StormXMLObject()
                acq_p = to_save.addSubSection("acquisition")
                acq_p.add(params.ParameterString(name = "version",
                                                 value = hgit.getVersion()))
                acq_p.add(params.ParameterInt(name = "number_frames",
                                              value = number_frames))
                for response in message.getResponses():
                    data = response.getData()

                    # Add general parameters 'en-bloc'.
                    if "parameters" in data:
                        to_save.addSubSection(response.source,
                                              svalue = data["parameters"])

                    # Add any acquisition parameters, these will be a list.
                    if "acquisition" in data:
                        for p in data["acquisition"]:
                            acq_p.addParameter(p.getName(), p)
                            if (p.getName() == "notes"):
                                notes = p.getv()

                to_save.saveToFile(film_settings.getBasename() + ".xml")

                if self.logfile_fp is not None:
                    msg = ",".join([str(datetime.datetime.now()),
                                    film_settings.getBasename(),
                                    notes])
                    msg += "\r\n"
                    self.logfile_fp.write(msg)
                    self.logfile_fp.flush()

            # Now that everything is complete end the filming lock out.
            self.setLockout(False, acquisition_parameters = acq_p)
Example #22
0
def infToStormXML(inf_filename):
    """
    Creates a StormXMLObject from a .inf file that can be
    used by Steve. Note that this object is missing many
    of the properties of the standard object created from
    a setting xml file.
    """

    xml = parameters.StormXMLObject([])

    # Mark as "fake".
    xml.set("faked_xml", True)

    # Add acquisition sub-object.
    xml.set("acquisition", parameters.StormXMLObject([]))
    xml.set("acquisition.camera", "camera1")

    # Add camera1 sub-object.
    xml.set("camera1", parameters.StormXMLObject([]))

    # Add film sub-object.
    xml.set("film", parameters.StormXMLObject([]))

    # Add mosaic sub-object with fake objective.
    xml.set("mosaic", parameters.StormXMLObject([]))
    xml.set("mosaic.objective", "fake")

    # Figure out movie type.
    no_ext_name = os.path.splitext(inf_filename)[0]
    if os.path.exists(no_ext_name + ".dax"):
        xml.set("film.filetype", ".dax")
    elif os.path.exists(no_ext_name + ".tif"):
        xml.set("film.filetype", ".tif")
    else:
        raise IOError("only .dax and .tif are supported (case sensitive..)")

    # Extract the movie information from the associated inf file.
    size_re = re.compile(r'frame dimensions = ([\d]+) x ([\d]+)')
    length_re = re.compile(r'number of frames = ([\d]+)')
    endian_re = re.compile(r' (big|little) endian')
    stagex_re = re.compile(r'Stage X = ([\d\.\-]+)')
    stagey_re = re.compile(r'Stage Y = ([\d\.\-]+)')
    scalemax_re = re.compile(r'scalemax = ([\d\.\-]+)')
    scalemin_re = re.compile(r'scalemin = ([\d\.\-]+)')
    parameters_re = re.compile(r'parameters file = (.+)')

    with open(inf_filename) as fp:
        for line in fp:
            m = size_re.match(line)
            if m:
                # y_pixels = height, x_pixels = width.
                xml.set("camera1.y_pixels", int(m.group(2)))
                xml.set("camera1.x_pixels", int(m.group(1)))

            m = length_re.match(line)
            if m:
                xml.set("acquisition.number_frames", int(m.group(1)))

            m = endian_re.search(line)
            if m:
                if (m.group(1) == "big"):
                    xml.set("film.want_big_endian", True)
                else:
                    xml.set("film.want_big_endian", False)

            m = stagex_re.match(line)
            if m:
                stage_x = float(m.group(1))

            m = stagey_re.match(line)
            if m:
                stage_y = float(m.group(1))

            m = scalemax_re.match(line)
            if m:
                xml.set("display00.camera1.scalemax", int(m.group(1)))

            m = scalemin_re.match(line)
            if m:
                xml.set("display00.camera1.scalemin", int(m.group(1)))

            m = parameters_re.match(line)
            if m:
                xml.set("parameters_file", m.group(1))

    pos_string = "{0:.2f},{1:.2f},0.00".format(stage_x, stage_y)
    xml.set("acquisition.stage_position", pos_string)
    return xml
Example #23
0
    def __init__(self, w1=None, configuration=None, **kwds):
        super().__init__(**kwds)
        self.w1 = w1

        # assert max_speed is not None

        # Create dictionaries for the configuration of the
        # filter wheels and two dichroic mirror sets.
        self.filter_wheel_config = {}
        values = configuration.get("filter_wheel")
        filter_names = values.split(",")
        for pos, filter_name in enumerate(filter_names):
            self.filter_wheel_config[filter_name] = pos + 1

        self.dichroic_mirror_config = {}
        values = configuration.get("dichroic_mirror")
        dichroic_names = values.split(",")
        for pos, dichroic_name in enumerate(dichroic_names):
            self.dichroic_mirror_config[dichroic_name] = pos + 1

        # Create parameters
        self.parameters = params.StormXMLObject()

        self.parameters.add(
            params.ParameterSetBoolean(
                description="Bypass spinning disk for brightfield mode?",
                name="bright_field_bypass",
                value=False))

        self.parameters.add(
            params.ParameterSetBoolean(description="Spin the disk?",
                                       name="spin_disk",
                                       value=True))

        # Disk properties
        self.parameters.add(
            params.ParameterSetString(
                description="Disk pinhole size",
                name="disk",
                value="70-micron pinholes",
                allowed=["70-micron pinholes", "40-micron pinholes"]))

        # Dichroic mirror position
        values = sorted(self.dichroic_mirror_config.keys())
        self.parameters.add(
            params.ParameterSetString(
                description="Dichroic mirror position (1-5)",
                name="dichroic_mirror",
                value=values[0],
                allowed=values))

        # Filter wheel positions
        values = sorted(self.filter_wheel_config.keys())
        self.parameters.add(
            params.ParameterSetString(
                description="Camera 1 Filter Wheel Position (1-8)",
                name="filter_wheel",
                value=values[0],
                allowed=values))

        self.newParameters(self.parameters, initialization=True)
Example #24
0
    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]
            }})
Example #25
0
    def __init__(self, parameters = None, **kwds):
        """
        parameters - This is just the 'feed' section of the parameters.
        """
        super().__init__(**kwds)

        self.feeds = {}
        if parameters is None:
            return

        # Create the feeds.
        self.parameters = parameters
        for feed_name in self.parameters.getAttrs():
            file_params = self.parameters.get(feed_name)
            
            # Create default feed parameters.
            max_value = 100000
            feed_params = params.StormXMLObject()

            # Feeds are saved with their name as the extension.
            feed_params.add(params.ParameterString(name = "extension",
                                                   value = feed_name,
                                                   is_mutable = True))
            
            feed_params.add(params.ParameterString(name = "feed_type",
                                                   value = "",
                                                   is_mutable = False))

            feed_params.add(params.ParameterSetBoolean(name = "saved",
                                                       value = False))

            # This is the camera that drives the feed.
            feed_params.add(params.ParameterString(name = "source",
                                                   value = "",
                                                   is_mutable = False))
            
            feed_params.add(params.ParameterRangeInt(description = "AOI X start.",
                                                     name = "x_start",
                                                     value = 1,
                                                     min_value = 1,
                                                     max_value = max_value))

            feed_params.add(params.ParameterRangeInt(description = "AOI X end.",
                                                     name = "x_end",
                                                     value = 1,
                                                     min_value = 1,
                                                     max_value = max_value))

            feed_params.add(params.ParameterRangeInt(description = "AOI Y start.",
                                                     name = "y_start",
                                                     value = 1,
                                                     min_value = 1,
                                                     max_value = max_value))
            
            feed_params.add(params.ParameterRangeInt(description = "AOI Y end.",
                                                     name = "y_end",
                                                     value = 1,
                                                     min_value = 1,
                                                     max_value = max_value))

            # Figure out what type of feed this is.
            fclass = None
            feed_type = file_params.get("feed_type")
            if (feed_type == "average"):
                fclass = FeedFunctionalityAverage
                
                feed_params.add(params.ParameterInt(description = "Number of frames to average.",
                                                    name = "frames_to_average",
                                                    value = 1))
                            
            elif (feed_type == "interval"):
                fclass = FeedFunctionalityInterval

                feed_params.add(params.ParameterInt(description = "Interval cycle length.",
                                                    name = "cycle_length",
                                                    value = 1))
                
                feed_params.add(params.ParameterCustom(description = "Frames to capture.",
                                                       name = "capture_frames",
                                                       value = "1"))

            elif (feed_type == "slice"):
                fclass = FeedFunctionalitySlice
            else:
                raise FeedException("Unknown feed type '" + feed_type + "' in feed '" + feed_name + "'")

            # Update with values from the parameters file. Depending on the parameters
            # file it might include parameters that we don't have and which we silently
            # ignore.
            #
            for attr in file_params.getAttrs():
                if feed_params.has(attr):
                    feed_params.setv(attr, file_params.get(attr))

            # Replace the values in the parameters that were read from a file with these values.
            self.parameters.addSubSection(feed_name, feed_params, overwrite = True)

            camera_name = feed_params.get("source") + "." + feed_name
            self.feeds[camera_name] = fclass(feed_name = feed_name,
                                             camera_name = camera_name,
                                             parameters = feed_params)