Exemple #1
0
class DisplayThread(QtCore.QThread):
    spectrum_ready = QtCore.Signal(np.ndarray)
    spectra_ready = QtCore.Signal(list)

    def __init__(self, parent):
        super(DisplayThread, self).__init__()
        self.parent = parent
        self.single_shot = False
        self.refresh_rate = 30.

    def run(self):
        t0 = time.time()
        while self.parent.live_button.isChecked() or self.single_shot:
            read_processed_spectrum = self.parent.spectrometer.read_processed_spectra \
                if isinstance(self.parent.spectrometer, Spectrometers) \
                else self.parent.spectrometer.read_processed_spectrum
            spectrum = read_processed_spectrum()
            if time.time() - t0 < 1. / self.refresh_rate:
                continue
            else:
                t0 = time.time()
            if type(spectrum) == np.ndarray:
                self.spectrum_ready.emit(spectrum)
            elif type(spectrum) == list:
                self.spectra_ready.emit(spectrum)
            if self.single_shot:
                break
        self.finished.emit()
Exemple #2
0
class CameraPreviewWidget(pg.GraphicsView):
    """A Qt Widget to display the live feed from a camera."""
    update_data_signal = QtCore.Signal(np.ndarray)

    def __init__(self):
        super(CameraPreviewWidget, self).__init__()

        self.image_item = PreviewImageItem()
        self.view_box = PreviewViewBox(lockAspect=1.0, invertY=True)
        self.view_box.addItem(self.image_item)
        self.view_box.setBackgroundColor([128, 128, 128, 255])
        self.setCentralWidget(self.view_box)
        self.crosshair = {
            'h_line': pg.InfiniteLine(pos=0, angle=0),
            'v_line': pg.InfiniteLine(pos=0, angle=90),
        }
        for item in self.crosshair.values():
            self.view_box.addItem(item)
        self._image_shape = ()

        # We want to make sure we always update the data in the GUI thread.
        # This is done using the signal/slot mechanism
        self.update_data_signal.connect(self.update_widget,
                                        type=QtCore.Qt.QueuedConnection)

    def update_widget(self, newimage):
        """Set the image, but do so in the Qt main loop to avoid threading nasties."""
        # I've explicitly dealt with the datatype of the source image, to avoid
        # a bug in the way pyqtgraph interacts with numpy 1.10.  This means
        # scaling the display values will fail for integer data.  I've thus
        # forced floating-point for anything that isn't a u8, and assumed u8
        # wants to be displayed raw.  You can always use filter_function to
        # tweak the brightness/contrast.
        if len(newimage.shape) == 2:
            newimage = newimage.transpose()
        elif len(newimage.shape) == 3:
            newimage = newimage.transpose((1, 0, 2))
        if newimage.dtype == "uint8":
            self.image_item.setImage(newimage, autoLevels=False)
        else:
            self.image_item.setImage(newimage.astype(float))
        if newimage.shape != self._image_shape:
            self._image_shape = newimage.shape
            self.set_crosshair_centre(
                (newimage.shape[1] / 2.0, newimage.shape[0] / 2.0))

    def update_image(self, newimage):
        """Update the image displayed in the preview widget."""
        # NB compared to previous versions, pyqtgraph flips in y, hence the
        # funny slice on the next line.
        self.update_data_signal.emit(newimage)

    def add_legacy_click_callback(self, function):
        """Add an old-style (coordinates in fractions-of-an-image) callback."""
        self.image_item.legacy_click_callback = function

    def set_crosshair_centre(self, pos):
        """Move the crosshair to centre on a given pixel coordinate."""
        self.crosshair['h_line'].setValue(pos[0])
        self.crosshair['v_line'].setValue(pos[1])
Exemple #3
0
class PowerMeterUI(QtWidgets.QWidget, UiTools):
    update_data_signal = QtCore.Signal(np.ndarray)

    def __init__(self, pm):
        super(PowerMeterUI, self).__init__()
        uic.loadUi(os.path.join(os.path.dirname(__file__), 'power_meter.ui'),
                   self)
        self.pm = pm
        self.update_condition = threading.Condition()
        self.display_thread = DisplayThread(self)
        self.SetupSignals()
        register_for_property_changes(self.pm, 'live', self.live_changed)

    def SetupSignals(self):
        self.read_pushButton.clicked.connect(self.button_pressed)
        self.live_button.clicked.connect(self.button_pressed)
        self.display_thread.ready.connect(self.update_display)

    def button_pressed(self):
        if self.sender() == self.read_pushButton:
            self.display_thread.single_shot = True
        elif self.sender() == self.live_button:
            self.pm.live = self.live_button.isChecked()
        self.display_thread.start()

    def update_display(self, power):
        self.power_lcdNumber.display(float(power))

    def live_changed(self, new):
        if self.live_button.isChecked() is not self.pm.live:
            self.live_button.setChecked(new)
        self.display_thread.start()
Exemple #4
0
class OxfordITCUI(QtWidgets.QWidget):
    updateGUI = QtCore.Signal()

    def __init__(self, itc):
        assert isinstance(itc, OxfordITC), "instrument must be an Oxford ITC"
        super(OxfordITCUI, self).__init__()

        self.ITC = itc

        uic.loadUi(os.path.join(os.path.dirname(__file__), 'OxfordITC.ui'), self)

        self.lineEditSetT.returnPressed.connect(self.setT)

        self.updateGUI.connect(self.SentUpdateGUI)
        self.SentUpdateGUI()

    def SentUpdateGUI(self):
        self.textEditT.setText(str(self.ITC.params['T']))
        self.lineEditSetT.setText(str(self.ITC.params['SetT']))
        self.lineEditP.setText(str(self.ITC.params['PID'][0]))
        self.lineEditI.setText(str(self.ITC.params['PID'][1]))
        self.lineEditD.setText(str(self.ITC.params['PID'][2]))
        return

    def setT(self):
        temp = float(self.lineEditSetT.text())
        self.ITC.setSetTemperature(temp)
Exemple #5
0
    def __init__(self, solstis):
        QtCore.QThread.__init__(self)
        self.SolsTiS = solstis
        self.signal = QtCore.SIGNAL("SolsTiS_status_update")

        self.setTerminationEnabled()

        self.SolsTiS.system_status()
Exemple #6
0
 def parent(self, index=None):
     """Find the index of the parent of the item at a given index."""
     try:
         parent = self._index_to_item(index).parent
         return self.createIndex(parent.row, 0, parent)
     except:
         # Something went wrong with finding the parent so return an invalid index
         return QtCore.QModelIndex()
Exemple #7
0
    def __init__(self, solstis):
        QtCore.QThread.__init__(self)
        self.SolsTiS = solstis
        self.signal = QtCore.SIGNAL("laser_unlocked")

        self.setTerminationEnabled()

        self.SolsTiS.system_status()
        if self.SolsTiS.laser_status['etalon_lock'] != 'on':
            self.SolsTiS.etalon_lock('on')
Exemple #8
0
    def index(self, row, column, parent_index):
        """Return the index of the <row>th child of parent

        :type row: int
        :type column: int
        :type parent: QtCore.QModelIndex
        """
        try:
            parent = self._index_to_item(parent_index)
            return self.createIndex(row, column, parent.children[row])
        except:
            return QtCore.QModelIndex()
Exemple #9
0
class QProgressDialogWithDeferredUpdate(QtWidgets.QProgressDialog):
    """A QProcessDialog that can have its value updated from a background thread."""
    set_new_value = QtCore.Signal(int)

    def __init__(self, *args, **kwargs):
        QtWidgets.QProgressDialog.__init__(self, *args, **kwargs)
        self.set_new_value.connect(self.setValue,
                                   type=QtCore.Qt.QueuedConnection)

    def setValueLater(self, progress):
        """Update the progress bar - but do it in a thread-safe way."""
        self.set_new_value.emit(progress)
Exemple #10
0
class FigureCanvasWithDeferredDraw(FigureCanvas):
    # This class allows us to use Qt's event loop to draw the canvas from
    # the GUI thread, even if the call comes from outside the GUI thread.
    # this is necessary if you want to plot from a background thread.
    ask_for_redraw = QtCore.Signal()

    def __init__(self, figure):
        FigureCanvas.__init__(self, figure)
        # We connect the ask_for_redraw signal to the FigureCanvas's draw() method.
        # using a QueuedConnection ensures that draw() is correctly called in the
        # application's main GUI thread.
        self.ask_for_redraw.connect(self.draw, type=QtCore.Qt.QueuedConnection)

    def draw_in_main_loop(self):
        """Draw the canvas, but do so in the Qt main loop to avoid threading nasties."""
        self.ask_for_redraw.emit()
Exemple #11
0
class PreviewImageItem(pg.ImageItem):
    legacy_click_callback = None
    click_callback_signal = QtCore.Signal(np.ndarray)

    def mouseClickEvent(self, ev):
        """Handle a mouse click on the image."""
        if ev.button() == QtCore.Qt.LeftButton:
            pos = np.array(ev.pos())
            if self.legacy_click_callback is not None:
                #        size = np.array(self.image.shape[:2])
                #           point = pos/size
                #          self.legacy_click_callback(point[1], point[0])
                self.legacy_click_callback(int(pos[1]), int(pos[0]))
                print pos[1], pos[0]
                ev.accept()
            else:
                pass
        else:
            super(PreviewImageItem, self).mouseClickEvent(ev)
Exemple #12
0
    def __init__(self, solstis):
        assert isinstance(solstis, SolsTiS), "instrument must be a SolsTiS"
        super(SolsTiSUI, self).__init__()

        self.SolsTiS = solstis
        self.signal = QtCore.SIGNAL('SolsTiSGUIupdate')
        self.SolsTiSMonitorThread = None

        uic.loadUi(os.path.join(os.path.dirname(__file__), 'SolsTiS.ui'), self)

        self.checkBoxSolsTiSLockMonitor.stateChanged.connect(
            self.SolsTiSLockMonitor)
        self.checkBoxSolsTiSEtalonLock.stateChanged.connect(
            self.SolsTiSLockEtalon)
        self.checkBoxSolsTiSCavityLock.stateChanged.connect(
            self.SolsTiSLockCavity)
        self.lineEditSolsTiSWL.returnPressed.connect(self.SolsTiSWL)
        self.pushButtonSolsTiSstatusMonitor.clicked.connect(
            self.SolsTiSMonitor)
        self.pushButtonSolsTiSstopMonitor.clicked.connect(
            self.SolsTiSMonitorStop)
Exemple #13
0
class DisplayThread(QtCore.QThread):
    ready = QtCore.Signal(float)

    def __init__(self, parent):
        super(DisplayThread, self).__init__()
        self.parent = parent
        self.single_shot = False
        self.refresh_rate = 4.

    def run(self):
        t0 = time.time()
        while self.parent.pm.live or self.single_shot:
            p = self.parent.pm.power
            if time.time() - t0 < 1. / self.refresh_rate:
                continue
            else:
                t0 = time.time()
            self.ready.emit(p)
            if self.single_shot:
                self.single_shot = False
                break
        self.finished.emit()
Exemple #14
0
class DisplayThread(QtCore.QThread):
    '''for displaying the temperature'''
    ready = QtCore.Signal(float)

    def __init__(self, parent):
        super(DisplayThread, self).__init__()
        self.parent = parent
        self.single_shot = False
        self.refresh_rate = 1.  # every second

    def run(self):
        t0 = time.time()
        while self.parent.live_temperature_checkBox.isChecked(
        ) or self.single_shot:
            T = self.parent.get_temperature()
            if time.time() - t0 < 1. / self.refresh_rate:
                continue
            else:
                t0 = time.time()
            self.ready.emit(T)
            if self.single_shot:
                self.single_shot = False
                break
        self.finished.emit()
Exemple #15
0
class CounterPreviewWidget(QtWidgets.QWidget):
    """A Qt Widget to display the live feed from a camera."""
    update_data_signal = QtCore.Signal(np.ndarray)

    def __init__(self, counter):
        super(CounterPreviewWidget, self).__init__()

        #   self.plot_item = pg.pl

        self.plot_widget = pg.PlotWidget(labels={'bottom': 'Time'})
        self.plot = self.plot_widget.getPlotItem()
        self.setLayout(QtWidgets.QGridLayout())
        self.layout().addWidget(self.plot_widget)
        self.counter = counter
        # We want to make sure we always update the data in the GUI thread.
        # This is done using the signal/slot mechanism
        self.update_data_signal.connect(self.update_widget,
                                        type=QtCore.Qt.QueuedConnection)

    def update_widget(self, new_data):
        """Set the data to the latest"""
        #    print 'update',new_data
        self.plot.clear()
        self.plot.plot(new_data[:, 1] - new_data[0, 1], new_data[:, 0])
Exemple #16
0
class AndorUI(QtWidgets.QWidget, UiTools):
    ImageUpdated = QtCore.Signal()

    def __init__(self, andor):
        assert isinstance(andor, Andor), "instrument must be an Andor"
        super(AndorUI, self).__init__()
        self.Andor = andor
        self.DisplayWidget = None
        self.temperature_display_thread = DisplayThread(self)
        uic.loadUi((os.path.dirname(__file__) + '/andor.ui'), self)

        self._setup_signals()
        self.init_gui()
        self.binning()
        self.data_file = None
        self.save_all_parameters = False

        self.gui_params = [
            'ReadMode', 'Exposure', 'AcquisitionMode', 'OutAmp', 'TriggerMode'
        ]
        self._func_dict = {}
        for param in self.gui_params:
            func = self.callback_to_update_prop(param)
            self._func_dict[param] = func
            register_for_property_changes(self.Andor, param,
                                          self._func_dict[param])
        if self.Andor.SingleTrack is not None:
            c_row, n_rows = self.Andor.SingleTrack
            self.spinBoxCenterRow.setValue(c_row)
            self.spinBoxNumRows.setValue(n_rows)

    def __del__(self):
        self._stopTemperatureThread = True
        if self.DisplayWidget is not None:
            self.DisplayWidget.hide()
            self.DisplayWidget.close()

    def _setup_signals(self):
        self.comboBoxAcqMode.activated.connect(self.acquisition_mode)
        self.comboBoxBinning.activated.connect(self.binning)
        self.comboBoxReadMode.activated.connect(self.read_mode)
        self.comboBoxTrigMode.activated.connect(self.trigger)
        self.spinBoxNumFrames.valueChanged.connect(self.number_frames)
        self.spinBoxNumFrames.setRange(1, 1000000)
        self.spinBoxNumAccum.valueChanged.connect(self.number_accumulations)
        self.spinBoxNumRows.valueChanged.connect(self.number_rows)
        self.spinBoxCenterRow.valueChanged.connect(self.number_rows)
        self.checkBoxROI.stateChanged.connect(self.ROI)
        self.checkBoxCrop.stateChanged.connect(self.isolated_crop)
        self.checkBoxCooler.stateChanged.connect(self.cooler)
        self.checkBoxEMMode.stateChanged.connect(self.output_amplifier)
        self.spinBoxEMGain.valueChanged.connect(self.em_gain)
        self.lineEditExpT.editingFinished.connect(self.exposure)
        self.lineEditExpT.setValidator(QtGui.QDoubleValidator())
        self.pushButtonDiv5.clicked.connect(lambda: self.exposure('/'))
        self.pushButtonTimes5.clicked.connect(lambda: self.exposure('x'))

        self.pushButtonCapture.clicked.connect(self.Capture)
        self.pushButtonLive.clicked.connect(self.Live)
        self.pushButtonAbort.clicked.connect(self.Abort)
        self.save_pushButton.clicked.connect(self.Save)
        self.pushButtonTakeBG.clicked.connect(self.take_background)
        self.checkBoxRemoveBG.stateChanged.connect(self.remove_background)
        self.referesh_groups_pushButton.clicked.connect(self.update_groups_box)
        self.keep_shutter_open_checkBox.stateChanged.connect(
            self.update_shutter_mode)
        self.read_temperature_pushButton.clicked.connect(self.temperature_gui)
        self.live_temperature_checkBox.clicked.connect(self.temperature_gui)
        self.temperature_display_thread.ready.connect(
            self.update_temperature_display)

    def init_gui(self):
        trig_modes = {0: 0, 1: 1, 6: 2}
        self.comboBoxAcqMode.setCurrentIndex(
            self.Andor._parameters['AcquisitionMode'] - 1)
        self.acquisition_mode()
        self.comboBoxReadMode.setCurrentIndex(
            self.Andor._parameters['ReadMode'])
        self.read_mode()
        self.comboBoxTrigMode.setCurrentIndex(
            trig_modes[self.Andor._parameters['TriggerMode']])
        self.trigger()
        self.comboBoxBinning.setCurrentIndex(
            np.log2(self.Andor._parameters['Image'][0]))
        self.binning()
        self.spinBoxNumFrames.setValue(self.Andor._parameters['NKin'])
        self.checkBoxEMMode.setChecked(not bool(self.Andor.OutAmp))
        if len(self.Andor.capabilities['EMGainCapability']) == 0:
            self.checkBoxEMMode.hide()
            self.spinBoxEMGain.hide()

        self.Andor.get_camera_parameter('AcquisitionTimings')
        self.lineEditExpT.setText(
            str(float(
                '%#e' %
                self.Andor._parameters['AcquisitionTimings'][0])).rstrip('0'))

    def cooler(self):
        self.Andor.cooler = self.checkBoxCooler.isChecked()

    def temperature_gui(self):
        if self.sender() == self.read_temperature_pushButton:
            self.temperature_display_thread.single_shot = True
        self.temperature_display_thread.start()

    def update_temperature_display(self, temperature):
        self.temperature_lcdNumber.display(float(temperature))

    def get_temperature(self):
        return self.Andor.CurrentTemperature

    def update_shutter_mode(self):
        self.Andor.keep_shutter_open = self.keep_shutter_open_checkBox.isChecked(
        )

    def acquisition_mode(self):
        available_modes = ['Single', 'Accumulate', 'Kinetic', 'Fast Kinetic']
        currentMode = self.comboBoxAcqMode.currentText()
        self.Andor.set_camera_parameter('AcquisitionMode',
                                        available_modes.index(currentMode) + 1)

        if currentMode == 'Fast Kinetic':
            self.spinBoxNumRows.show()
            self.labelNumRows.show()

        elif currentMode != 'Single track':
            self.spinBoxNumRows.hide()
            self.labelNumRows.hide()

        if currentMode == 'Accumulate':
            self.spinBoxNumAccum.show()
            self.labelNumAccum.show()
        else:
            self.spinBoxNumAccum.hide()
            self.labelNumAccum.hide()

        if (currentMode == 'Fast Kinetic') or (currentMode == 'Kinetic'):
            self.keep_shutter_open_checkBox.show()
        else:
            self.keep_shutter_open_checkBox.hide()

    def read_mode(self):
        available_modes = [
            'FVB', 'Multi-track', 'Random track', 'Single track', 'Image'
        ]
        currentMode = self.comboBoxReadMode.currentText()
        self.Andor.set_camera_parameter('ReadMode',
                                        available_modes.index(currentMode))
        if currentMode == 'Single track':
            self.spinBoxNumRows.show()
            self.labelNumRows.show()
            self.spinBoxCenterRow.show()
            self.labelCenterRow.show()
        elif self.comboBoxAcqMode.currentText() != 'Fast Kinetic':
            self.spinBoxNumRows.hide()
            self.labelNumRows.hide()
            self.spinBoxCenterRow.hide()
            self.labelCenterRow.hide()
        else:
            self.spinBoxCenterRow.hide()
            self.labelCenterRow.hide()

    def update_ReadMode(self, index):
        self.comboBoxReadMode.setCurrentIndex(index)

    def update_TriggerMode(self, value):
        available_modes = {0: 0, 1: 1, 6: 2}
        index = available_modes[value]
        self.comboBoxTrigMode.setCurrentIndex(index)

    def update_Exposure(self, value):
        self.lineEditExpT.setText(str(value))

    def callback_to_update_prop(self, propname):
        """Return a callback function that refreshes the named parameter."""
        def callback(value=None):
            getattr(self, 'update_' + propname)(value)

        return callback

    def trigger(self):
        available_modes = {'Internal': 0, 'External': 1, 'ExternalStart': 6}
        currentMode = self.comboBoxTrigMode.currentText()
        self.Andor.set_camera_parameter('TriggerMode',
                                        available_modes[currentMode])

    def output_amplifier(self):
        self.Andor.OutAmp = int(not self.checkBoxEMMode.isChecked())
        self.checkBoxCrop.setChecked(False)

    def binning(self):
        current_binning = int(self.comboBoxBinning.currentText()[0])
        self.Andor.binning = current_binning
        self.Andor.FVBHBin = current_binning

    def number_frames(self):
        num_frames = self.spinBoxNumFrames.value()
        self.Andor.set_camera_parameter('NKin', num_frames)

    def number_accumulations(self):
        num_frames = self.spinBoxNumAccum.value()
        self.Andor.set_camera_parameter('NAccum', num_frames)

    def number_rows(self):
        num_rows = self.spinBoxNumRows.value()
        if self.Andor._parameters['AcquisitionMode'] == 4:
            self.Andor.set_fast_kinetics(num_rows)
        elif self.Andor._parameters['ReadMode'] == 3:
            center_row = self.spinBoxCenterRow.value()
            if center_row - num_rows < 0:
                self.Andor._logger.info(
                    'Too many rows provided for Single Track mode. Using %g rows instead'
                    % center_row)
                num_rows = center_row
            self.Andor.set_camera_parameter('SingleTrack', center_row,
                                            num_rows)
        else:
            self.Andor._logger.info(
                'Changing the rows only works in Fast Kinetic or in Single Track mode'
            )

    def exposure(self, input=None):
        if input is None:
            expT = float(self.lineEditExpT.text())
        elif input == 'x':
            expT = float(self.lineEditExpT.text()) * 5
        elif input == '/':
            expT = float(self.lineEditExpT.text()) / 5
        self.Andor.Exposure = expT

    def em_gain(self):
        gain = self.spinBoxEMGain.value()
        self.Andor.set_camera_parameter('EMGain', gain)

    def isolated_crop(self):
        current_binning = self.Andor.binning
        gui_roi = self.Andor.gui_roi
        maxy = gui_roi[3]
        if self.checkBoxEMMode.isChecked():
            maxx = gui_roi[1]
        else:
            shape = self.Andor.DetectorShape
            maxx = shape[0] - gui_roi[1]

        if self.checkBoxCrop.isChecked():
            self.checkBoxROI.setEnabled(False)
            self.Andor.IsolatedCropMode = (1, maxy, maxx, current_binning[0],
                                           current_binning[1])
            self.Andor.Image = (current_binning[0], current_binning[1], 1,
                                maxx, 1, maxy)
        else:
            self.checkBoxROI.setEnabled(True)
            self.Andor.IsolatedCropMode = (0, maxy, maxx, current_binning[0],
                                           current_binning[1])
            shape = self.Andor.DetectorShape
            self.Andor.Image = (current_binning[0], current_binning[1], 1,
                                shape[0], 1, shape[1])

    def take_background(self):
        self.Andor.background = self.Andor.raw_snapshot()[1]
        self.Andor.backgrounded = True
        self.checkBoxRemoveBG.setChecked(True)

    def remove_background(self):
        if self.checkBoxRemoveBG.isChecked():
            self.Andor.backgrounded = True
        else:
            self.Andor.backgrounded = False

    def Save(self):
        if self.data_file is None:
            self.data_file = df.current()
        data = self.Andor.CurImage
        if self.filename_lineEdit.text() != 'Filename....':
            filename = self.filename_lineEdit.text()
        else:
            filename = 'Andor_data'
        if self.group_comboBox.currentText() == 'AndorData':
            if df._use_current_group == True and df._current_group is not None:
                group = df._current_group
            elif 'AndorData' in list(self.data_file.keys()):
                group = self.data_file['AndorData']
            else:
                group = self.data_file.create_group('AndorData')
        else:
            group = self.data_file[self.group_comboBox.currentText()]
        if np.shape(data)[0] == 1:
            data = data[0]
        if self.save_all_parameters:
            attrs = self.Andor.get_andor_parameters()
        else:
            attrs = dict()
        attrs['Description'] = self.description_plainTextEdit.toPlainText()
        if hasattr(self.Andor, 'x_axis'):
            attrs['wavelengths'] = self.Andor.x_axis
        try:
            data_set = group.create_dataset(name=filename, data=data)
        except Exception as e:
            self.Andor._logger.info(e)
        df.attributes_from_dict(data_set, attrs)
        if self.Andor.backgrounded == False and 'background' in list(
                data_set.attrs.keys()):
            del data_set.attrs['background']

    def update_groups_box(self):
        if self.data_file is None:
            self.data_file = df.current()
        self.group_comboBox.clear()
        if 'AndorData' not in list(self.data_file.values()):
            self.group_comboBox.addItem('AndorData')
        for group in list(self.data_file.values()):
            if type(group) == df.Group:
                self.group_comboBox.addItem(group.name[1:], group)

    def ROI(self):
        if self.checkBoxROI.isChecked():
            self.checkBoxCrop.setEnabled(False)
            self.Andor.roi = self.Andor.gui_roi  # binning + params
        else:
            self.checkBoxCrop.setEnabled(True)
            self.Andor.roi = (0,
                              self.Andor._parameters['DetectorShape'][0] - 1,
                              0,
                              self.Andor._parameters['DetectorShape'][1] - 1)

    def Capture(self):
        self.Andor.raw_image(update_latest_frame=True)

    def Live(self):
        self.Andor.live_view = True

    def Abort(self):
        self.Andor.live_view = False
Exemple #17
0
class DisplayWidgetRoiScale(ExtendedImageView):
    _max_num_line_plots = 4
    update_data_signal = QtCore.Signal(np.ndarray)

    def __init__(self, scale=(1, 1), offset=(0, 0)):
        super(DisplayWidgetRoiScale, self).__init__()

        self._pxl_scale = scale
        self._pxl_offset = offset

        self.LineDisplay = self.ui.roiPlot
        self.LineDisplay.showGrid(x=True, y=True)
        self.ui.splitter.setHandleWidth(10)
        self.getHistogramWidget().gradient.restoreState(
            list(Gradients.values())[1])
        self.imageItem.setTransform(QtGui.QTransform())
        self.LineDisplay.show()

        self.plot = ()
        for ii in range(self._max_num_line_plots):
            self.plot += (self.LineDisplay.plot(
                pen=pyqtgraph.intColor(ii, self._max_num_line_plots)), )

        self.toggle_displays()

        self.checkbox_autorange = QtWidgets.QCheckBox('Autorange')
        self.tools.gridLayout.addWidget(self.checkbox_autorange, 0, 3, 1, 1)

    @property
    def x_axis(self):
        """Convenience wrapper for integration with spectrometer code"""
        return self.axis_values['bottom']

    @x_axis.setter
    def x_axis(self, value):
        self.axis_values['bottom'] = value

    @property
    def y_axis(self):
        """Convenience wrapper for integration with spectrometer code"""
        return self.axis_values['left']

    @y_axis.setter
    def y_axis(self, value):
        self.axis_values['left'] = value

    def update_axes(self):
        gui_axes = self.get_axes()
        for ax, name in zip(gui_axes, ["bottom", "left", "top", "right"]):
            if self.axis_values[name] is not None:
                setattr(ax, 'axis_values', self.axis_values[name])
            if self.axis_units[name] is not None:
                ax.setLabel(self.axis_units[name])

        # This is kept in case subclasses overwrite the x_axis or y_axis properties
        for ax, value in zip(gui_axes[:2], [self.x_axis, self.y_axis]):
            if value is not None:
                setattr(ax, 'axis_values', value)

    def toggle_displays(self, boolean=False):
        """Toggle between an Image display and a Plot widget for Line displays

        :param boolean: if True, display lines. If False, display images
        :return:
        """
        if boolean:
            self.LineDisplay.show()
            self.LineDisplay.showAxis('left')
            self.ui.splitter.setSizes([0, self.height() - 35, 35])
        else:
            self.ui.splitter.setSizes([self.height() - 35, 0, 35])

    def update_image(self, newimage):
        scale = self._pxl_scale
        offset = self._pxl_offset

        if len(newimage.shape) == 1:
            self.toggle_displays(True)
            self.plot[0].setData(x=self.x_axis, y=newimage)
        elif len(newimage.shape) == 2:
            if newimage.shape[0] > self._max_num_line_plots:
                self.toggle_displays(False)
                # levels = [np.percentile(newimage, x) for x in self.levels()]
                self.setImage(
                    newimage,
                    pos=offset,
                    autoRange=self.checkbox_autorange.isChecked(),
                    # levels=levels,
                    scale=scale)
            else:
                self.toggle_displays(True)
                for ii, ydata in enumerate(newimage):
                    self.plot[ii].setData(x=self.x_axis, y=ydata)
        elif len(newimage.shape) == 3:
            self.toggle_displays(False)
            zvals = 0.99 * np.linspace(0, newimage.shape[0] - 1,
                                       newimage.shape[0])
            if newimage.shape[0] == 1:
                newimage = newimage[0]
            # levels = [np.percentile(newimage, x) for x in self.levels()]
            self.setImage(
                newimage,
                xvals=zvals,
                pos=offset,
                autoRange=self.checkbox_autorange.isChecked(),
                # levels=levels,
                scale=scale)
        else:
            raise ValueError('Cannot display. Array shape unrecognised')
Exemple #18
0
class StreakUI(QtWidgets.QWidget):
    ImageUpdated = QtCore.Signal()

    def __init__(self, streak):
        super(StreakUI, self).__init__()

        self.Streak = streak
        uic.loadUi((os.path.dirname(__file__) + '/Streak.ui'), self)

        self.comboBoxGateMode.activated.connect(self.gate_mode)
        self.comboBoxReadMode.activated.connect(self.read_mode)
        self.comboBoxShutter.activated.connect(self.shutter)
        self.comboBoxTrigMode.activated.connect(self.trigger)
        self.spinBox_MCPGain.valueChanged.connect(self.mcp_gain)
        self.lineEditTimeRange.returnPressed.connect(self.time_range)
        self.comboBoxTimeUnit.activated.connect(self.time_range)
        self.pushButtonLess.clicked.connect(lambda: self.time_range('-'))
        self.pushButtonMore.clicked.connect(lambda: self.time_range('+'))

        self.pushButtonCapture.clicked.connect(
            lambda: self.Streak.raw_image(update_latest_frame=True))

    def gate_mode(self):
        mode = str(self.comboBoxGateMode.currentText())
        self.Streak.set_parameter('Devices', 'TD', 'Gate Mode', mode)

    def read_mode(self):
        mode = str(self.comboBoxReadMode.currentText())
        self.Streak.set_parameter('Devices', 'TD', 'Mode', mode)

    def shutter(self):
        mode = str(self.comboBoxShutter.currentText())
        self.Streak.set_parameter('Devices', 'TD', 'Shutter', mode)

    def trigger(self):
        mode = str(self.comboBoxTrigMode.currentText())
        self.Streak.set_parameter('Devices', 'TD', 'Trig. Mode', mode)

    def mcp_gain(self):
        gain = int(self.spinBox_MCPGain.value())
        self.Streak.set_parameter('Devices', 'TD', 'MCP Gain', gain)

    def time_range(self, direction=None):
        allowed_times = {
            'ns': [5, 10, 20, 50, 100, 200, 500],
            'us': [1, 2, 5, 10, 20, 50, 100, 200, 500],
            'ms': [1]
        }
        unit = str(self.comboBoxTimeUnit.currentText())
        given_number = int(self.lineEditTimeRange.text())

        if direction is '+':
            if not (unit == 'ms' and given_number == 1):
                next_unit = str(unit)
                if given_number != 500:
                    next_number = allowed_times[unit][
                        allowed_times[unit].index(given_number) + 1]
                else:
                    next_number = 1
                    if unit == 'ns':
                        self.comboBoxTimeUnit.setCurrentIndex(1)
                        next_unit = 'us'
                    elif unit == 'us':
                        self.comboBoxTimeUnit.setCurrentIndex(2)
                        next_unit = 'ms'
                self.lineEditTimeRange.setText(str(next_number))
                unit = str(next_unit)
            else:
                self.Streak._logger.info(
                    'Tried increasing the maximum time range')
                return
        elif direction is '-':
            if not (unit == 'ns' and given_number == 5):
                next_unit = str(unit)
                if given_number != 1:
                    next_number = allowed_times[unit][
                        allowed_times[unit].index(given_number) - 1]
                else:
                    next_number = 500
                    if unit == 'ms':
                        self.comboBoxTimeUnit.setCurrentIndex(1)
                        next_unit = 'us'
                    elif unit == 'us':
                        self.comboBoxTimeUnit.setCurrentIndex(0)
                        next_unit = 'ns'
                self.lineEditTimeRange.setText(str(next_number))
                unit = str(next_unit)
            else:
                self.Streak._logger.info(
                    'Tried decreasing the minimum time range')
                return
        else:
            next_number = min(allowed_times[unit],
                              key=lambda x: abs(x - given_number))
            self.lineEditTimeRange.setText(str(next_number))

        # Some camera models don't give you direct access to the time range, but rather you preset a finite number of
        # settings that you then switch between
        try:
            self.Streak.set_parameter('Devices', 'TD', 'Time Range',
                                      str(next_number) + ' ' + unit)
        except StreakError:
            self.Streak.set_parameter('Devices', 'TD', 'Time Range',
                                      str(next_number))
Exemple #19
0
class Frequency_counter_F390(SerialInstrument):
    port_settings = dict(baudrate=115200,
                         bytesize=serial.EIGHTBITS,
                         parity=serial.PARITY_NONE,
                         xonxoff=True,
                         timeout=1.0)
    termination_character = "\n"
    update_data_signal = QtCore.Signal(np.ndarray)

    def __init__(self, port=None, integration_time=1):
        SerialInstrument.__init__(self, port=port)
        self.live_window = 100
        self._live_view = False
        self.int_time = integration_time
        self.write('FO')  #do not apply low pass filter
        self.write('Z5')  #for 50 Ohms impedance

    function_dict = {
        '0': 'B Input Period',
        '1': 'A Input Period',
        '2': 'A Input Frequency',
        '3': 'B Input Frequency',
        '4': 'Frequency Ratio B:A',
        '5': 'A Input Width High',
        '6': 'A Input Width Low',
        '7': 'A Input Count',
        '8': 'A Input Ratio H:L',
        '9': 'A Input Duty Cycle',
        'C': 'C Input Frequency',
        'D': 'C Input Period'
    }

    def get_function(self):
        '''A property to set the required function of the frequency counter
        Args:
            f: the a string value of the function shown in the table below and in self.function_dict
            
            0 B Input Period
            1 A Input Period
            2 A Input Frequency
            3 B Input Frequency
            4 Frequency Ratio B:A
            5 A Input Width High
            6 A Input Width Low
            7 A Input Count
            8 A Input Ratio H:L
            9 A Input Duty Cycle
            C C Input Frequency
            D C Input Period
        returns:
            the current function
            '''
        return self.function_dict(self._function)

    def set_function(self, f):
        self._function = str(f)
        self.write('F' + str(f))

    function = property(fget=get_function, fset=set_function)

    def get_identity(self):
        '''Returns the device id (good for testing comms) '''
        return self.query('*IDN?')

    def test_communications(self):
        '''A command to allow autodetection to work '''
        if self.get_identity().split(',')[0] == 'Thurlby-Thandar':
            return True

    def measure_next(self):
        '''Return the next valid measurement'''
        try:
            return float(self.query('N?')[:-2])
        except:
            print(self.query('N?')[:-2])

    def measure_next_fast(self):
        '''Return the invalid measurement (i.e. refereshs at LCD refresh rate, not the measreument rate)'''
        try:
            return float(self.query('?')[:-2])
        except:
            print(self.query('?')[:-2])


#    def start_countinous_fast(self):
#        '''Starts fast streaming of values at the LCD refresh rate '''
#        self.write('C?')
#    def start_countinous_single(self):
#        '''Starts continuous streaming of values at the rate of the measurement time'''
#        self.write('E?')
#    def stop_countinous(self):
#        self.write('STOP')

    def get_live_view_window(self):
        return self._live_window

    def set_live_view_window(self, window_length):
        self._live_window = window_length
        '''Set the number of the stored values in the deque '''
        self.live_deque = deque(maxlen=window_length)

    live_window = NotifiedProperty(get_live_view_window, set_live_view_window)

    int_times = {0.3: '1', 1: '2', 10: '3', 100: '4'}
    impedances = {'50': 'Z5', '1M': 'Z1'}

    def get_int_time(self):
        '''A property for the integration time possible values are:
                0.3 s, 1s, 10s,100s '''
        return self._int_time

    def set_int_time(self, integration_time):
        self._int_time = integration_time
        try:
            self.write('M' + self.int_times[integration_time])
        except KeyError:
            self.log('Invalid integration time', level='WARN')

    int_time = NotifiedProperty(get_int_time, set_int_time)

    def get_qt_ui(self):
        self.ui = CounterUI(self)
        self.display_ui = self.ui.preview_widget
        self.control_ui = self.ui.control_widget
        return self.ui

    def get_preview_widget(self):
        self.display_ui = CounterPreviewWidget(self)
        return self.display_ui

    def get_control_widget(self):
        self.control_ui = CounterControlUI(self)
        return self.control_ui

    def _live_view_function(self):
        '''The function that is run within the live preview thread '''
        while self._live_view:
            data = None
            data = self.measure_next_fast()
            #     while data == None:
            time.sleep(self.int_time)
            self.live_deque.append([data, time.time()])
            self.display_ui.update_data_signal.emit(np.array(self.live_deque))

    def get_live_view(self):
        '''Setting up the notificed property
        live view to allow live view to be switch on and off '''
        return self._live_view

    def set_live_view(self, enabled):
        if enabled == True:
            try:
                self._live_view = True
                self._live_view_stop_event = threading.Event()
                self._live_view_thread = threading.Thread(
                    target=self._live_view_function)
                self._live_view_thread.start()
            except AttributeError as e:  #if any of the attributes aren't there
                print("Error:", e)
        else:
            if not self._live_view:
                return  # do nothing if it's not running.
            print("stopping live view thread")
            try:
                self._live_view = False
                self._live_view_stop_event.set()
                self._live_view_thread.join()
                del (self._live_view_stop_event, self._live_view_thread)
            except AttributeError:
                raise Exception(
                    "Tried to stop live view but it doesn't appear to be running!"
                )

    live_view = NotifiedProperty(get_live_view, set_live_view)
Exemple #20
0
 def sizeHint(self):
     return QtCore.QSize(1024, 768)