Example #1
0
class Main(GUIBase):
    """ GUI module to interface a spectrometer """

    spectrumlogic = Connector(interface='SpectrumLogic')
    savelogic = Connector(interface='SaveLogic')

    _cooler_temperature_unit = ConfigOption('cooler_temperature_unit')

    _alignment_read_mode = StatusVar('alignment_read_mode', 'FVB')
    _alignment_exposure_time = StatusVar('alignment_exposure_time', 0)
    _alignment_time_window = StatusVar('alignment_time_window', 60)

    _image_read_mode = StatusVar('image_read_mode', 'IMAGE_ADVANCED')
    _image_acquisition_mode = StatusVar('image_acquisition_mode', 'LIVE')
    _image_exposure_time = StatusVar('image_exposure_time', None)
    _image_readout_speed = StatusVar('image_readout_speed', None)

    _spectrum_read_mode = StatusVar('spectrum_read_mode', 'MULTIPLE_TRACKS')
    _spectrum_acquisition_mode = StatusVar('spectrum_acquisition_mode',
                                           'SINGLE_SCAN')
    _spectrum_exposure_time = StatusVar('spectrum_exposure_time', None)
    _spectrum_readout_speed = StatusVar('spectrum_readout_speed', None)

    _image_data = StatusVar('image_data', np.zeros((1000, 1000)))
    _image_dark = StatusVar('image_dark', np.zeros((1000, 1000)))
    _image_params = StatusVar('image_params', dict())
    _counter_data = StatusVar('counter_data', np.zeros((2, 1000)))
    _spectrum_data = StatusVar('spectrum_data', np.zeros((2, 1000)))
    _spectrum_dark = StatusVar('spectrum_dark', np.zeros(1000))
    _spectrum_params = StatusVar('spectrum_params', dict())

    def __init__(self, config, **kwargs):
        super().__init__(config=config, **kwargs)

    def on_activate(self):
        """ Definition and initialisation of the GUI. """

        # setting up the window
        self._mw = MainWindow()
        self._settings_tab = SettingsTab()
        self._image_tab = ImageTab()
        self._alignment_tab = AlignmentTab()
        self._spectrum_tab = SpectrumTab()

        self._mw.tab.addTab(self._settings_tab, "Settings")
        self._mw.tab.addTab(self._image_tab, "Image")
        self._mw.tab.addTab(self._alignment_tab, "Alignment")
        self._mw.tab.addTab(self._spectrum_tab, "Spectrum")

        self._acquire_dark_buttons = []
        self._start_acquisition_buttons = []
        self._stop_acquisition_buttons = []
        self._save_data_buttons = []

        self._track_buttons = [
            self._image_tab.track1, self._image_tab.track2,
            self._image_tab.track3, self._image_tab.track4
        ]
        self._track_selector = []

        if not self._image_exposure_time:
            self._image_exposure_time = self.spectrumlogic().exposure_time
        if not self._image_readout_speed:
            self._image_readout_speed = self.spectrumlogic().readout_speed
        if not self._alignment_exposure_time:
            self._alignment_exposure_time = self.spectrumlogic().exposure_time
        if not self._spectrum_exposure_time:
            self._spectrum_exposure_time = self.spectrumlogic().exposure_time
        if not self._spectrum_readout_speed:
            self._spectrum_readout_speed = self.spectrumlogic().readout_speed

        self._activate_settings_tab()
        self._activate_image_tab()
        self._activate_alignment_tab()
        self._activate_spectrum_tab()
        self._settings_window = [
            self._image_tab.image_settings,
            self._alignment_tab.counter_settings,
            self._spectrum_tab.spectrum_settings
        ]

        self._manage_stop_acquisition()

    def on_deactivate(self):
        """ Deinitialisation performed during deactivation of the module.
        """
        self._alignment_read_mode = self._alignment_tab.read_modes.currentData(
        )
        self._alignment_exposure_time = self.alignment_exposure_time_widget.value(
        )
        self._image_acquisition_mode = self._image_tab.acquisition_modes.currentData(
        )
        self._image_read_mode = self._image_tab.read_modes.currentData()
        self._image_exposure_time = self.image_exposure_time_widget.value()
        self._image_readout_speed = self._image_tab.readout_speed.currentData()
        self._spectrum_acquisition_mode = self._spectrum_tab.acquisition_modes.currentData(
        )
        self._spectrum_read_mode = self._spectrum_tab.read_modes.currentData()
        self._spectrum_exposure_time = self.spectrum_exposure_time_widget.value(
        )
        self._spectrum_readout_speed = self._spectrum_tab.readout_speed.currentData(
        )
        self._mw.close()

    def show(self):
        """ Make window visible and put it above all other windows """
        QtWidgets.QMainWindow.show(self._mw)
        self._mw.activateWindow()
        self._mw.raise_()

    def _activate_settings_tab(self):
        """ Initialization method for the setting tab """

        spectro_constraints = self.spectrumlogic().spectro_constraints

        self._grating_buttons = [
            self._settings_tab.grating_1, self._settings_tab.grating_2,
            self._settings_tab.grating_3
        ]
        self._input_port_buttons = [
            self._settings_tab.input_front, self._settings_tab.input_side
        ]
        self._input_slit_width = []
        self._output_port_buttons = [
            self._settings_tab.output_front, self._settings_tab.output_side
        ]
        self._output_slit_width = []

        for i in range(3):
            self._grating_buttons[i].setText('{}rpm'.format(
                round(
                    self.spectrumlogic().spectro_constraints.gratings[i].ruling
                    / 1000)))
            self._grating_buttons[i].setCheckable(True)
            self._grating_buttons[i].clicked.connect(
                partial(self._manage_grating_buttons, i))
            if i == self.spectrumlogic().grating:
                self._grating_buttons[i].setDown(True)

        self._input_ports = [
            port for port in spectro_constraints.ports
            if port.type in [PortType.INPUT_FRONT, PortType.INPUT_SIDE]
        ]
        self._output_ports = [
            port for port in spectro_constraints.ports
            if port.type in [PortType.OUTPUT_FRONT, PortType.OUTPUT_SIDE]
        ]

        for i in range(2):

            if i < len(self._input_ports):

                self._input_port_buttons[i].setText(
                    self._input_ports[i].type.name[6:].lower())
                self._input_port_buttons[i].setCheckable(True)
                if self._input_ports[i].type.name == self.spectrumlogic(
                ).input_port:
                    self._input_port_buttons[i].setDown(True)

                input_widget = ScienDSpinBox()
                input_widget.setRange(self._input_ports[i].constraints.min,
                                      self._input_ports[i].constraints.max)
                input_widget.setValue(
                    self.spectrumlogic().get_input_slit_width(
                        self._input_ports[i].type.name))
                input_widget.setSuffix('m')
                input_widget.editingFinished.connect(
                    partial(self._manage_slit_width, i))
                self._input_slit_width.append(input_widget)

                self._settings_tab.input_layout.addWidget(input_widget, i, 2)
                if len(self._input_ports) > 1:
                    self._input_port_buttons[i].clicked.connect(
                        partial(self._manage_port_buttons, i))

            else:
                self._input_port_buttons[i].setEnabled(False)

            if i < len(self._output_ports):

                self._output_port_buttons[i].setText(
                    self._output_ports[i].type.name[7:].lower())
                self._output_port_buttons[i].setCheckable(True)
                if self._output_ports[i].type.name == self.spectrumlogic(
                ).output_port:
                    self._output_port_buttons[i].setDown(True)

                output_widget = ScienDSpinBox()
                output_widget.setRange(self._output_ports[i].constraints.min,
                                       self._output_ports[i].constraints.max)
                output_widget.setValue(
                    self.spectrumlogic().get_output_slit_width(
                        self._output_ports[i].type.name))
                output_widget.setSuffix('m')
                output_widget.editingFinished.connect(
                    partial(self._manage_slit_width, i + 2))
                self._output_slit_width.append(output_widget)

                self._settings_tab.output_layout.addWidget(output_widget, i, 2)
                if len(self._output_ports) > 1:
                    self._output_port_buttons[i].clicked.connect(
                        partial(self._manage_port_buttons, i + 2))

            else:
                self._output_port_buttons[i].setEnabled(False)

        self._calibration_widget = ScienDSpinBox()
        self._calibration_widget.setValue(
            self.spectrumlogic().wavelength_calibration)
        self._calibration_widget.setSuffix('m')
        self._settings_tab.calibration_layout.addWidget(
            self._calibration_widget)

        for gain in self.spectrumlogic().camera_constraints.internal_gains:
            self._settings_tab.camera_gains.addItem(str(gain), gain)
            if gain == self.spectrumlogic().camera_gain:
                self._settings_tab.camera_gains.setCurrentText(str(gain))

        for trigger_mode in self.spectrumlogic(
        ).camera_constraints.trigger_modes:
            self._settings_tab.trigger_modes.addItem(trigger_mode,
                                                     trigger_mode)
            if trigger_mode == self.spectrumlogic().trigger_mode:
                self._settings_tab.trigger_modes.setCurrentText(trigger_mode)

        self._temperature_widget = ScienDSpinBox()
        self._temperature_widget.setRange(-273.15, 500)
        self._temperature_widget.setValue(
            self.spectrumlogic().temperature_setpoint - 273.15)
        self._temperature_widget.setSuffix('°C')
        self._settings_tab.camera_cooler_layout.addWidget(
            self._temperature_widget)

        self._settings_tab.cooler_on.clicked.connect(
            self._manage_cooler_button)
        if self.spectrumlogic().cooler_status:
            self._settings_tab.cooler_on.setDown(True)
            self._settings_tab.cooler_on.setText("OFF")
            self._mw.cooler_on_label.setText("Cooler ON")
        else:
            self._settings_tab.cooler_on.setText("ON")
            self._mw.cooler_on_label.setText("Cooler OFF")
        self._mw.camera_temperature.setText("{}°C".format(
            round(self.spectrumlogic().camera_temperature - 273.15, 2)))

        self._center_wavelength_widget = ScienDSpinBox()
        self._center_wavelength_widget.setMinimum(0)
        self._center_wavelength_widget.setValue(
            self.spectrumlogic().center_wavelength)
        self._center_wavelength_widget.setSuffix("m")
        self._mw.center_wavelength.addWidget(self._center_wavelength_widget, 1)
        self._mw.go_to_wavelength.clicked.connect(
            self._manage_center_wavelength)
        self._mw.center_wavelength_current.setText("{:.2r}m".format(
            ScaledFloat(self.spectrumlogic().center_wavelength)))

        self._calibration_widget.editingFinished.connect(
            self.set_settings_params)
        self._settings_tab.camera_gains.currentTextChanged.connect(
            self.set_settings_params)
        self._settings_tab.trigger_modes.currentTextChanged.connect(
            self.set_settings_params)
        self._temperature_widget.editingFinished.connect(
            self.set_settings_params)
        if not self.spectrumlogic().camera_constraints.has_shutter:
            self._settings_tab.shutter_modes.setEnabled(False)
        else:
            self._settings_tab.shutter_modes.setCurrentText(
                self.spectrumlogic().shutter_state)
            self._settings_tab.shutter_modes.currentTextChanged.connect(
                self.set_settings_params)

        self._update_temperature_timer = QtCore.QTimer()
        self._update_temperature_timer.timeout.connect(
            self._update_temperature)
        self._update_temperature_timer.start(1000)

        self.spectrumlogic().sigUpdateSettings.connect(self._update_settings)

    def _activate_image_tab(self):
        """ Initialization method for the image tab """

        camera_width = self.spectrumlogic().camera_constraints.width
        camera_height = self.spectrumlogic().camera_constraints.height

        for read_mode in self.spectrumlogic().camera_constraints.read_modes:
            if read_mode.name[:5] == "IMAGE":
                self._image_tab.read_modes.addItem(read_mode.name,
                                                   read_mode.name)
                if read_mode == self._image_read_mode:
                    self._image_tab.read_modes.setCurrentText(read_mode.name)

        for acquisition_mode in AcquisitionMode.__members__:
            if acquisition_mode != "MULTI_SCAN":
                self._image_tab.acquisition_modes.addItem(
                    acquisition_mode, acquisition_mode)
                if acquisition_mode == self._image_acquisition_mode:
                    self._image_tab.acquisition_modes.setCurrentText(
                        acquisition_mode)

        self.image_exposure_time_widget = ScienDSpinBox()
        self.image_exposure_time_widget.setMinimum(0)
        self.image_exposure_time_widget.setValue(self._image_exposure_time)
        self.image_exposure_time_widget.setSuffix('s')
        self._image_tab.exposure_time_layout.addWidget(
            self.image_exposure_time_widget)

        for readout_speed in self.spectrumlogic(
        ).camera_constraints.readout_speeds:
            self._image_tab.readout_speed.addItem(
                "{:.2r}Hz".format(ScaledFloat(readout_speed)), readout_speed)
            if readout_speed == self._image_readout_speed:
                self._image_tab.readout_speed.setCurrentText("{:.2r}Hz".format(
                    ScaledFloat(readout_speed)))

        self._image_tab.save.clicked.connect(partial(self.save_data, 0))
        self._save_data_buttons.append(self._image_tab.save)
        self._image_tab.acquire_dark.clicked.connect(
            partial(self.start_dark_acquisition, 0))
        self._acquire_dark_buttons.append(self._image_tab.acquire_dark)
        self._image_tab.start_acquisition.clicked.connect(
            partial(self.start_acquisition, 0))
        self._start_acquisition_buttons.append(
            self._image_tab.start_acquisition)
        self._image_tab.stop_acquisition.clicked.connect(self.stop_acquisition)
        self._stop_acquisition_buttons.append(self._image_tab.stop_acquisition)
        self._image_tab.remove_dark.clicked.connect(
            partial(self.remove_dark, 0))

        self.my_colors = ColorScaleInferno()
        self._image = pg.ImageItem(image=self._image_data,
                                   axisOrder='row-major')
        self._image.setLookupTable(self.my_colors.lut)
        self._image_tab.graph.addItem(self._image)
        self._colorbar = ColorbarWidget(self._image)
        self._image_tab.colorbar.addWidget(self._colorbar)

        self.track_colors = np.array(
            [palette.c5, palette.c2, palette.c6, palette.c4])
        self.plot_colors = self.track_colors
        height = self.spectrumlogic().camera_constraints.height
        for i in range(4):
            self._track_buttons[i].setCheckable(True)
            self._track_buttons[i].clicked.connect(
                partial(self._manage_track_buttons, i))
            tracks = self.spectrumlogic().active_tracks
            if 2 * i < len(tracks):
                top_pos = tracks[2 * i]
                bottom_pos = tracks[2 * i + 1]
            else:
                top_pos = 0
                bottom_pos = 10
            color = self.track_colors[i].getRgb()
            track_color = pg.mkBrush(color[0], color[1], color[2], 100)
            track = pg.LinearRegionItem(
                values=[top_pos, bottom_pos],
                orientation=pg.LinearRegionItem.Horizontal,
                brush=track_color)
            track.setBounds([0, height])
            track.hide()
            self._track_selector.append(track)
            self._image_tab.graph.addItem(track)

        self._image_tab.image_advanced.setCheckable(True)
        self._image_tab.image_advanced.clicked.connect(
            self._manage_image_advanced_button)
        self._image_advanced_widget = pg.ROI(
            [0, 0], [camera_width, camera_height],
            maxBounds=QRectF(QPoint(0, 0), QPoint(camera_width,
                                                  camera_height)))
        self._image_advanced_widget.addScaleHandle((1, 0), (0, 1))
        self._image_advanced_widget.addScaleHandle((0, 1), (1, 0))
        self._image_advanced_widget.hide()
        self._image_tab.graph.addItem(self._image_advanced_widget)

        self._image_tab.horizontal_binning.setRange(1, camera_width - 1)
        self._image_tab.vertical_binning.setRange(1, camera_height - 1)

        self._image_tab.horizontal_binning.editingFinished.connect(
            self.set_image_params)
        self._image_tab.vertical_binning.editingFinished.connect(
            self.set_image_params)
        self._image_tab.read_modes.currentTextChanged.connect(
            self.set_image_params)
        self._image_tab.acquisition_modes.currentTextChanged.connect(
            self.set_image_params)
        self.image_exposure_time_widget.editingFinished.connect(
            self.set_image_params)
        self._image_tab.readout_speed.currentTextChanged.connect(
            self.set_image_params)

    def _activate_alignment_tab(self):

        self.time_window_widget = ScienDSpinBox()
        self.time_window_widget.setMinimum(0)
        self.time_window_widget.setValue(self._alignment_time_window)
        self.time_window_widget.setSuffix('s')
        self.time_window_widget.editingFinished.connect(
            self._change_time_window)
        self._alignment_tab.time_window_layout.addWidget(
            self.time_window_widget, 1)
        self._alignment_tab.clean.clicked.connect(self._clean_time_window)

        for read_mode in self.spectrumlogic().camera_constraints.read_modes:
            self._alignment_tab.read_modes.addItem(str(read_mode.name),
                                                   read_mode.name)
            if read_mode == self._alignment_read_mode:
                self._alignment_tab.read_modes.setCurrentText(
                    str(read_mode.name))

        self.alignment_exposure_time_widget = ScienDSpinBox()
        self.alignment_exposure_time_widget.setMinimum(0)
        self.alignment_exposure_time_widget.setValue(
            self._alignment_exposure_time)
        self.alignment_exposure_time_widget.setSuffix('s')
        self._alignment_tab.exposure_time_layout.addWidget(
            self.alignment_exposure_time_widget)
        self._change_time_window()

        self._alignment_tab.start_acquisition.clicked.connect(
            partial(self.start_acquisition, 1))
        self._start_acquisition_buttons.append(
            self._alignment_tab.start_acquisition)
        self._alignment_tab.stop_acquisition.clicked.connect(
            self.stop_acquisition)
        self._stop_acquisition_buttons.append(
            self._alignment_tab.stop_acquisition)

        self._alignment_tab.graph.setLabel('left',
                                           'photon counts',
                                           units='counts/s')
        self._alignment_tab.graph.setLabel('bottom',
                                           'acquisition time',
                                           units='s')
        self._counter_plot = self._alignment_tab.graph.plot(
            self._counter_data[0], self._counter_data[1])

        self._alignment_tab.read_modes.currentTextChanged.connect(
            self.set_alignment_params)
        self.alignment_exposure_time_widget.editingFinished.connect(
            self.set_alignment_params)

    def _activate_spectrum_tab(self):
        """ Initialization method for the spectrum tab """

        for read_mode in self.spectrumlogic().camera_constraints.read_modes:
            if read_mode.name[:5] != "IMAGE":
                self._spectrum_tab.read_modes.addItem(str(read_mode.name),
                                                      read_mode.name)
                if read_mode == self._spectrum_read_mode:
                    self._spectrum_tab.read_modes.setCurrentText(
                        str(read_mode.name))

        for acquisition_mode in AcquisitionMode.__members__:
            self._spectrum_tab.acquisition_modes.addItem(
                acquisition_mode, acquisition_mode)
            if acquisition_mode == self._spectrum_acquisition_mode:
                self._spectrum_tab.acquisition_modes.setCurrentText(
                    acquisition_mode)

        self.spectrum_exposure_time_widget = ScienDSpinBox()
        self.spectrum_exposure_time_widget.setMinimum(0)
        self.spectrum_exposure_time_widget.setValue(
            self._spectrum_exposure_time)
        self.spectrum_exposure_time_widget.setSuffix('s')
        self._spectrum_tab.exposure_time_layout.addWidget(
            self.spectrum_exposure_time_widget)

        for readout_speed in self.spectrumlogic(
        ).camera_constraints.readout_speeds:
            self._spectrum_tab.readout_speed.addItem(
                "{:.2r}Hz".format(ScaledFloat(readout_speed)), readout_speed)
            if readout_speed == self._spectrum_readout_speed:
                self._spectrum_tab.readout_speed.setCurrentText(
                    "{:.2r}Hz".format(ScaledFloat(readout_speed)))

        self._spectrum_scan_delay_widget = ScienDSpinBox()
        self._spectrum_scan_delay_widget.setMinimum(0)
        self._spectrum_scan_delay_widget.setValue(
            self.spectrumlogic().scan_delay)
        self._spectrum_scan_delay_widget.setSuffix('s')
        self._spectrum_tab.scan_delay.addWidget(
            self._spectrum_scan_delay_widget)

        self._spectrum_tab.scan_number_spin.setValue(
            self.spectrumlogic().number_of_scan)

        self._spectrum_tab.save.clicked.connect(partial(self.save_data, 1))
        self._save_data_buttons.append(self._spectrum_tab.save)
        self._spectrum_tab.acquire_dark.clicked.connect(
            partial(self.start_dark_acquisition, 1))
        self._acquire_dark_buttons.append(self._spectrum_tab.acquire_dark)
        self._spectrum_tab.start_acquisition.clicked.connect(
            partial(self.start_acquisition, 2))
        self._start_acquisition_buttons.append(
            self._spectrum_tab.start_acquisition)
        self._spectrum_tab.stop_acquisition.clicked.connect(
            self.stop_acquisition)
        self._stop_acquisition_buttons.append(
            self._spectrum_tab.stop_acquisition)
        self._spectrum_tab.remove_dark.clicked.connect(
            partial(self.remove_dark, 1))

        self._spectrum_tab.graph.setLabel('left',
                                          'Photoluminescence',
                                          units='counts/s')
        self._spectrum_tab.graph.setLabel('bottom', 'wavelength', units='m')

        self._spectrum_tab.read_modes.currentTextChanged.connect(
            self.set_spectrum_params)
        self._spectrum_tab.acquisition_modes.currentTextChanged.connect(
            self.set_spectrum_params)
        self.spectrum_exposure_time_widget.editingFinished.connect(
            self.set_spectrum_params)
        self._spectrum_tab.read_modes.currentTextChanged.connect(
            self.set_spectrum_params)
        self._spectrum_scan_delay_widget.editingFinished.connect(
            self.set_spectrum_params)
        self._spectrum_tab.scan_number_spin.editingFinished.connect(
            self.set_spectrum_params)

    def _update_settings(self):

        self._manage_grating_buttons(self.spectrumlogic()._grating)

        if len(self._input_ports) > 1:
            input_port_index = 0 if self.spectrumlogic(
            )._input_port == PortType.INPUT_FRONT else 1
            self._manage_port_buttons(input_port_index)
            self._input_slit_width[input_port_index].setValue(
                self.spectrumlogic()._input_slit_width[input_port_index])
        else:
            self._input_slit_width[0].setValue(
                self.spectrumlogic()._input_slit_width[0])
        if len(self._output_ports) > 1:
            output_port_index = 0 if self.spectrumlogic(
            )._output_port == PortType.OUTPUT_FRONT else 1
            self._manage_port_buttons(output_port_index + 2)
            self._output_slit_width[output_port_index].setValue(
                self.spectrumlogic()._output_slit_width[output_port_index])
        else:
            self._output_slit_width[0].setValue(
                self.spectrumlogic()._output_slit_width[0])

        self._calibration_widget.setValue(
            self.spectrumlogic()._wavelength_calibration[
                self.spectrumlogic()._grating])
        self._settings_tab.camera_gains.setCurrentText(
            str(int(self.spectrumlogic()._camera_gain)))
        self._settings_tab.trigger_modes.setCurrentText(
            self.spectrumlogic()._trigger_mode)
        self._temperature_widget.setValue(
            self.spectrumlogic()._temperature_setpoint - 273.15)

        cooler_on = self.spectrumlogic()._cooler_status
        if self._settings_tab.cooler_on.isDown() != cooler_on:
            self._settings_tab.cooler_on.setChecked(cooler_on)
            self._settings_tab.cooler_on.setDown(cooler_on)
            self._settings_tab.cooler_on.setText(
                "ON" if not cooler_on else "OFF")
            self._mw.cooler_on_label.setText(
                "Cooler {}".format("ON" if cooler_on else "OFF"))

        if self.spectrumlogic().camera_constraints.has_shutter:
            self._settings_tab.shutter_modes.setCurrentText(
                self.spectrumlogic()._shutter_state)

        self._mw.center_wavelength_current.setText("{:.2r}m".format(
            ScaledFloat(self.spectrumlogic()._center_wavelength)))

    def set_settings_params(self):

        if self.spectrumlogic().module_state() == 'locked':
            return

        self.spectrumlogic(
        ).wavelength_calibration = self._calibration_widget.value()
        self.spectrumlogic(
        ).camera_gain = self._settings_tab.camera_gains.currentData()
        self.spectrumlogic(
        ).trigger_mode = self._settings_tab.trigger_modes.currentData()
        self.spectrumlogic(
        ).temperature_setpoint = self._temperature_widget.value() + 273.15
        self.spectrumlogic(
        ).shutter_state = self._settings_tab.shutter_modes.currentText()

        self._mw.center_wavelength_current.setText("{:.2r}m".format(
            ScaledFloat(self.spectrumlogic().center_wavelength)))

    def set_image_params(self):

        if self.spectrumlogic().module_state() == 'locked':
            return

        self._manage_image_advanced()
        self.spectrumlogic(
        ).acquisition_mode = self._image_tab.acquisition_modes.currentData()
        self.spectrumlogic(
        ).read_mode = self._image_tab.read_modes.currentData()
        self.spectrumlogic(
        ).exposure_time = self.image_exposure_time_widget.value()
        self.spectrumlogic(
        ).readout_speed = self._image_tab.readout_speed.currentData()

        self.spectrumlogic()._update_acquisition_params()
        if self._image_params != self.spectrumlogic().acquisition_params:
            self._image_tab.dark_acquired_msg.setText("Dark Outdated")
        self._image_params = self.spectrumlogic().acquisition_params

    def set_alignment_params(self):

        if self.spectrumlogic().module_state() == 'locked':
            return

        self.spectrumlogic().acquisition_mode = "LIVE_SCAN"
        self.spectrumlogic(
        ).read_mode = self._alignment_tab.read_modes.currentData()
        self.spectrumlogic(
        ).exposure_time = self.alignment_exposure_time_widget.value()
        self.spectrumlogic().readout_speed = max(
            self.spectrumlogic().camera_constraints.readout_speeds)

        self._manage_tracks()
        self._change_time_window()

    def set_spectrum_params(self):

        if self.spectrumlogic().module_state() == 'locked':
            return

        self._manage_tracks()
        self.spectrumlogic(
        ).acquisition_mode = self._spectrum_tab.acquisition_modes.currentData(
        )
        self.spectrumlogic(
        ).read_mode = self._spectrum_tab.read_modes.currentData()
        self.spectrumlogic(
        ).exposure_time = self.spectrum_exposure_time_widget.value()
        self.spectrumlogic(
        ).readout_speed = self._spectrum_tab.readout_speed.currentData()
        self.spectrumlogic(
        ).scan_delay = self._spectrum_scan_delay_widget.value()
        self.spectrumlogic(
        ).number_of_scan = self._spectrum_tab.scan_number_spin.value()

        self.spectrumlogic()._update_acquisition_params()
        if self._spectrum_params != self.spectrumlogic().acquisition_params:
            self._spectrum_tab.dark_acquired_msg.setText("Dark Outdated")
        self._spectrum_params = self.spectrumlogic().acquisition_params

    def start_dark_acquisition(self, index):

        self._manage_start_acquisition(index)

        self.spectrumlogic().acquisition_mode = "SINGLE_SCAN"
        self.spectrumlogic().shutter_state = "CLOSED"
        self.spectrumlogic().sigUpdateData.connect(
            partial(self._update_dark, index))

        if index == 0:
            self.spectrumlogic(
            ).read_modes = self._image_tab.read_modes.currentData()
            self.spectrumlogic(
            ).exposure_time = self.image_exposure_time_widget.value()
            self.spectrumlogic(
            ).readout_speed = self._image_tab.readout_speed.currentData()
        elif index == 1:
            self.spectrumlogic(
            ).read_modes = self._spectrum_tab.read_modes.currentData()
            self.spectrumlogic(
            ).exposure_time = self.spectrum_exposure_time_widget.value()
            self.spectrumlogic(
            ).readout_speed = self._spectrum_tab.readout_speed.currentData()

        self.spectrumlogic().start_acquisition()

    def start_acquisition(self, index):

        self._manage_start_acquisition(index)
        self.spectrumlogic().sigUpdateData.connect(
            partial(self._update_data, index))

        if index == 0:
            self.set_image_params()
        elif index == 1:
            self.set_alignment_params()
        elif index == 2:
            self.set_spectrum_params()

        self.spectrumlogic().start_acquisition()

    def stop_acquisition(self):

        self.spectrumlogic().stop_acquisition()
        self.spectrumlogic().sigUpdateData.disconnect()
        self._manage_stop_acquisition()

    def _manage_grating_buttons(self, index):

        for i in range(3):
            btn = self._grating_buttons[i]
            if i == index:
                btn.setChecked(True)
                btn.setDown(True)
                self.spectrumlogic().grating = i
            else:
                btn.setChecked(False)
                btn.setDown(False)
        self._mw.center_wavelength_current.setText("{:.2r}m".format(
            ScaledFloat(self.spectrumlogic().center_wavelength)))
        self._calibration_widget.setValue(
            self.spectrumlogic().wavelength_calibration)

    def _manage_port_buttons(self, index):
        for i in range(2):
            if index < 2:
                btn = self._input_port_buttons[i]
                if i == index:
                    self.spectrumlogic().input_port = self.spectrumlogic(
                    ).spectro_constraints.ports[i].type
                    btn.setChecked(True)
                    btn.setDown(True)
                else:
                    btn.setChecked(False)
                    btn.setDown(False)
            elif index > 1:
                btn = self._output_port_buttons[i]
                if i + 2 == index:
                    self.spectrumlogic().output_port = self.spectrumlogic(
                    ).spectro_constraints.ports[i + 2].type
                    btn.setChecked(True)
                    btn.setDown(True)
                else:
                    btn.setChecked(False)
                    btn.setDown(False)

    def _manage_slit_width(self, index):

        if index < 2:
            self.spectrumlogic().set_input_slit_width(
                self._input_slit_width[index].value(),
                self._input_ports[index].type)
        elif index > 1:
            self.spectrumlogic().set_output_slit_width(
                self._output_slit_width[index - 2].value(),
                self._output_ports[index - 2].type)

    def _manage_cooler_button(self):
        cooler_on = not self.spectrumlogic().cooler_status
        self.spectrumlogic().cooler_status = cooler_on
        self._settings_tab.cooler_on.setChecked(cooler_on)
        self._settings_tab.cooler_on.setDown(cooler_on)
        self._settings_tab.cooler_on.setText("ON" if not cooler_on else "OFF")
        self._mw.cooler_on_label.setText(
            "Cooler {}".format("ON" if cooler_on else "OFF"))

    def _manage_center_wavelength(self):

        self.spectrumlogic(
        ).center_wavelength = self._center_wavelength_widget.value()
        self._mw.center_wavelength_current.setText("{:.2r}m".format(
            ScaledFloat(self.spectrumlogic().center_wavelength)))

    def _manage_tracks(self):
        active_tracks = []
        for i in range(4):
            if self._track_selector[i].isVisible():
                track = self._track_selector[i].getRegion()
                active_tracks.append(int(track[0]))
                active_tracks.append(int(track[1]))
        active_tracks = np.array(active_tracks)
        self.plot_colors[np.argsort(active_tracks[::2])]
        if np.any(self.spectrumlogic().active_tracks != active_tracks):
            self._spectrum_tab.dark_acquired_msg.setText("Dark Outdated")
            self.spectrumlogic().active_tracks = active_tracks

    def _manage_image_advanced(self):

        height = self.spectrumlogic().camera_constraints.height
        width = self.spectrumlogic().camera_constraints.width

        hbin = self._image_tab.horizontal_binning.value()
        vbin = self._image_tab.vertical_binning.value()
        image_binning = list((hbin, vbin))
        if list(self.spectrumlogic().image_advanced_binning.values()
                ) != image_binning:
            self._image_tab.dark_acquired_msg.setText("No Dark Acquired")
            self.spectrumlogic().image_advanced_binning = image_binning

        roi_size = self._image_advanced_widget.getArrayRegion(
            self._image_data, self._image).shape
        roi_origin = self._image_advanced_widget.pos()
        vertical_range = [int(roi_origin[0]), int(roi_origin[0]) + roi_size[0]]
        horizontal_range = [
            int(roi_origin[1]),
            int(roi_origin[1]) + roi_size[1]
        ]
        image_advanced = horizontal_range + vertical_range
        if list(self.spectrumlogic().image_advanced_area.values()
                ) != image_advanced:
            self._image_tab.dark_acquired_msg.setText("No Dark Acquired")
            self.spectrumlogic().image_advanced_area = image_advanced

    def _manage_track_buttons(self, index):

        track_selector = self._track_selector[index]
        if track_selector.isVisible():
            track_selector.hide()
        else:
            track_selector.setVisible(True)

    def _manage_image_advanced_button(self):

        if self._image_advanced_widget.isVisible():
            self._image_advanced_widget.hide()
        else:
            self._image_advanced_widget.setVisible(True)

    def _update_temperature(self):

        self._mw.camera_temperature.setText(
            str(round(self.spectrumlogic().camera_temperature - 273.15, 2)) +
            "°C")

    def _manage_start_acquisition(self, index):

        for i in range(3):
            self._settings_window[i].setEnabled(False)
            self._start_acquisition_buttons[i].setEnabled(False)
            if i == index:
                self._stop_acquisition_buttons[i].setEnabled(True)
            else:
                self._stop_acquisition_buttons[i].setEnabled(False)
            if i < 2:
                self._acquire_dark_buttons[i].setEnabled(False)
                self._save_data_buttons[i].setEnabled(False)
        self._spectrum_tab.multiple_scan_settings.setEnabled(False)

    def _manage_stop_acquisition(self):

        for i in range(3):
            self._settings_window[i].setEnabled(True)
            self._start_acquisition_buttons[i].setEnabled(True)
            self._stop_acquisition_buttons[i].setEnabled(False)
            if i < 2:
                self._acquire_dark_buttons[i].setEnabled(True)
                self._save_data_buttons[i].setEnabled(True)
        self._spectrum_tab.multiple_scan_settings.setEnabled(True)

    def _clean_time_window(self):

        time_window = self.time_window_widget.value()
        exposure_time = self.alignment_exposure_time_widget.value()
        number_points = int(time_window / exposure_time)
        self._counter_data = np.zeros((2, number_points))
        self._counter_plot.setData([])

    def _change_time_window(self):

        time_window = self.time_window_widget.value()
        exposure_time = self.alignment_exposure_time_widget.value()
        number_points = int(time_window / exposure_time)
        x = np.linspace(self._counter_data[0, -1] - time_window,
                        self._counter_data[0, -1], number_points)
        if self._counter_data.shape[1] < number_points:
            y = np.empty(number_points)
            y[-self._counter_data.shape[1]:] = self._counter_data[1]
        else:
            y = self._counter_data[1, -number_points:]
        self._counter_data = np.array([x, y])
        self._alignment_tab.graph.setRange(
            xRange=(x[-1] - self.time_window_widget.value(), x[-1]))

    def _update_data(self, index):

        data = self.spectrumlogic().acquired_data

        if index == 0:
            if self._image_dark.shape == data.shape:
                self._image_data = data - self._image_dark
            else:
                self._image_data = data
                self._image_tab.dark_acquired_msg.setText("No Dark Acquired")

            self._image.setImage(self._image_data)
            self._colorbar.refresh_image()

            if self.spectrumlogic().read_mode == "IMAGE_ADVANCED":
                rectf = self._image_advanced_widget.parentBounds()
                self._image.setRect(rectf)
            else:
                width = self.spectrumlogic().camera_constraints.width
                height = self.spectrumlogic().camera_constraints.height
                self._image.setRect(QtCore.QRect(0, 0, width, height))

        elif index == 1:

            counts = data.mean()
            x = self._counter_data[0] + self.spectrumlogic().exposure_time
            y = np.append(self._counter_data[1][1:], counts)
            self._counter_data = np.array([x, y])
            self._alignment_tab.graph.setRange(
                xRange=(x[-1] - self.time_window_widget.value(), x[-1]))
            self._counter_plot.setData(x, y)

        elif index == 2:

            x = self.spectrumlogic().wavelength_spectrum
            if self._spectrum_dark.shape[-1] == data.shape[-1]:
                # TODO : fix bug with dark in multiple tracks and data in FVB : broadcasting error
                y = data - self._spectrum_dark
            else:
                y = data
                self._spectrum_tab.dark_acquired_msg.setText(
                    "No Dark Acquired")

            if self.spectrumlogic().acquisition_mode == "MULTI_SCAN":
                self._spectrum_data = np.array([[x, scan] for scan in y])
                self._spectrum_tab.graph.clear()

                if self.spectrumlogic().read_mode == "MULTIPLE_TRACKS":
                    tracks = y[-1]
                    if self.spectrumlogic().number_of_scan == y.shape[0]:
                        if self._spectrum_tab.multipe_scan_mode.currentText(
                        ) == "Scan Average":
                            tracks = np.mean(y.transpose(0, 2, 1), axis=0).T
                        if self._spectrum_tab.multipe_scan_mode.currentText(
                        ) == "Scan Median":
                            tracks = np.median(y.transpose(0, 2, 1), axis=0).T
                    i = 0
                    for track in tracks:
                        self._spectrum_tab.graph.plot(x,
                                                      track,
                                                      pen=self.plot_colors[i])
                        i += 1
                else:
                    tracks = y[-1]
                    if self.spectrumlogic().number_of_scan == y.shape[0]:
                        if self._spectrum_tab.multipe_scan_mode.currentText(
                        ) == "Scan Average":
                            tracks = np.mean(y, axis=0)
                        if self._spectrum_tab.multipe_scan_mode.currentText(
                        ) == "Scan Median":
                            tracks = np.median(y, axis=0)
                    self._spectrum_tab.graph.plot(x,
                                                  tracks,
                                                  pen=self.plot_colors[0])
            else:
                self._spectrum_data = np.array([x, y])
                self._spectrum_tab.graph.clear()
                if self.spectrumlogic().read_mode == "MULTIPLE_TRACKS":
                    i = 0
                    for track in y:
                        self._spectrum_tab.graph.plot(x,
                                                      track,
                                                      pen=self.plot_colors[i])
                        i += 1
                else:
                    self._spectrum_tab.graph.plot(x,
                                                  y,
                                                  pen=self.plot_colors[0])

        if not self.spectrumlogic().module_state() == 'locked':
            self.spectrumlogic().sigUpdateData.disconnect()
            self._manage_stop_acquisition()

    def _update_dark(self, index):

        dark = self.spectrumlogic().acquired_data

        if index == 0:
            self._image_dark = dark
            self._image_tab.dark_acquired_msg.setText("Dark Acquired")
        elif index == 1:
            self._spectrum_dark = dark
            self._spectrum_tab.dark_acquired_msg.setText("Dark Acquired")

        self.spectrumlogic().sigUpdateData.disconnect()
        self._manage_stop_acquisition()
        self.spectrumlogic(
        ).shutter_state = self._settings_tab.shutter_modes.currentText()

    def remove_dark(self, index):

        if index == 0:
            self._image_dark = np.zeros((1000, 1000))
            self._image_tab.dark_acquired_msg.setText("No Dark Acquired")
        if index == 1:
            self._spectrum_dark = np.zeros(1000)
            self._spectrum_tab.dark_acquired_msg.setText("No Dark Acquired")

    def save_data(self, index):

        filepath = self.savelogic().get_path_for_module(
            module_name='spectrometer')

        if index == 0:
            data = {
                'data':
                np.array(self._image_data /
                         self._image_params['exposure_time (s)']).flatten()
            }
            self.savelogic().save_data(data,
                                       filepath=filepath,
                                       parameters=self._image_params)
        elif index == 1:
            data = {
                'data':
                np.array(self._spectrum_data /
                         self._spectrum_params['exposure_time (s)']).flatten()
            }
            self.savelogic().save_data(data,
                                       filepath=filepath,
                                       parameters=self._spectrum_params)
Example #2
0
class ColorbarWidget(QtWidgets.QWidget):
    """ Create the widget, based on the corresponding *.ui file."""
    def __init__(self, image_widget, unit='c/s'):
        # Get the path to the *.ui file
        this_dir = os.path.dirname(__file__)
        ui_file = os.path.join(this_dir, 'ui_colorbar.ui')

        # Load it
        super(ColorbarWidget, self).__init__()
        uic.loadUi(ui_file, self)

        self._cb_min = 0
        self._cb_max = 100
        self.unit = unit

        self.init_spin_box()
        self.init_colorbar()

        self.set_image(image_widget)

        self.percentile.clicked.emit()
        self.percentile.setChecked(True)

    def init_spin_box(self):
        """ Initialize all the spinboxes """
        self._min_percentile = ScienDSpinBox()
        self._min_manual = ScienDSpinBox()
        self._max_percentile = ScienDSpinBox()
        self._max_manual = ScienDSpinBox()

        self._min_percentile.setSuffix('%')
        self._min_percentile.setMinimum(0)
        self._min_percentile.setMaximum(100)
        self._min_percentile.setValue(0)

        self._min_manual.setSuffix(self.unit)

        self._max_percentile.setSuffix('%')
        self._max_percentile.setMinimum(0)
        self._max_percentile.setMaximum(100)
        self._max_percentile.setValue(100)

        self._max_manual.setSuffix(self.unit)

        self.min.addWidget(self._min_manual)
        self.min.addWidget(self._min_percentile)
        self.max.addWidget(self._max_percentile)
        self.max.addWidget(self._max_manual)

        self._min_percentile.valueChanged.connect(self.shortcut_to_cb_centiles)
        self._min_manual.valueChanged.connect(self.shortcut_to_cb_manual)
        self._max_percentile.valueChanged.connect(self.shortcut_to_cb_centiles)
        self._max_manual.valueChanged.connect(self.shortcut_to_cb_manual)

        self.manual.clicked.connect(self.update_cb_range)
        self.percentile.clicked.connect(self.update_cb_range)

    def init_colorbar(self):
        """ Create the colorbar """
        self.my_colors = ColorScaleInferno()
        self._color_map = ColorScaleMagma()
        self._cb = ColorBar(self.my_colors.cmap_normed,
                            width=100,
                            cb_min=self._cb_min,
                            cb_max=self._cb_max)
        self.colorbar.addItem(self._cb)
        self.colorbar.hideAxis('bottom')
        self.colorbar.setLabel('left', 'Intensity', units=self.unit)
        self.colorbar.setMouseEnabled(x=False, y=False)

    def set_image(self, image_widget):
        """ Set the image widget associated to the colorbar """
        self._image = image_widget
        self._min_manual.setValue(np.min(self._image.image))
        self._min_percentile.setValue(0)
        self._max_manual.setValue(np.max(self._image.image))
        self._max_percentile.setValue(100)
        self.refresh_colorbar()

    def get_cb_range(self):
        """ Determines the cb_min and cb_max values for the image """
        # If "Manual" is checked, or the image data is empty (all zeros), then take manual cb range.
        if self.manual.isChecked() or np.count_nonzero(self._image.image) < 1:
            cb_min = self._min_manual.value()
            cb_max = self._max_manual.value()

        # Otherwise, calculate cb range from percentiles.
        else:
            # Exclude any zeros (which are typically due to unfinished scan)
            image_nonzero = self._image.image[np.nonzero(self._image.image)]

            # Read centile range
            low_centile = self._min_percentile.value()
            high_centile = self._max_percentile.value()

            cb_min = np.percentile(image_nonzero, low_centile)
            cb_max = np.percentile(image_nonzero, high_centile)

        cb_range = [cb_min, cb_max]

        return cb_range

    def refresh_colorbar(self):
        """ Adjust the colorbar. """
        cb_range = self.get_cb_range()
        self._cb.refresh_colorbar(cb_range[0], cb_range[1])

    def refresh_image(self):
        """ Update the image colors range."""

        image_data = self._image.image
        cb_range = self.get_cb_range()
        self._image.setImage(image=image_data,
                             levels=(cb_range[0], cb_range[1]))
        self.refresh_colorbar()

    def update_cb_range(self):
        """ Redraw colour bar and image."""
        self.refresh_colorbar()
        self.refresh_image()

    def shortcut_to_cb_manual(self):
        """ Someone edited the absolute counts range for the colour bar, better update."""
        self.manual.setChecked(True)
        self.update_cb_range()

    def shortcut_to_cb_centiles(self):
        """Someone edited the centiles range for the colour bar, better update."""
        self.percentile.setChecked(True)
        self.update_cb_range()