def set_sounds_and_volume(self):
        self.soundsGroup = QtGui.QActionGroup(self.menuSounds)
        self.soundsGroup.setExclusive(True)
        self.actionBeep.setActionGroup(self.soundsGroup)
        self.actionBeep.triggered.connect(self.toggle_sounds)
        self.actionClick.setActionGroup(self.soundsGroup)
        self.actionClick.triggered.connect(self.toggle_sounds)
        self.actionPunch.setActionGroup(self.soundsGroup)
        self.actionPunch.triggered.connect(self.toggle_sounds)
        self.actionWhack.setActionGroup(self.soundsGroup)
        self.actionWhack.triggered.connect(self.toggle_sounds)
        self.actionSharp.setActionGroup(self.soundsGroup)
        self.actionSharp.triggered.connect(self.toggle_sounds)
        self.actionGlass.setActionGroup(self.soundsGroup)
        self.actionGlass.triggered.connect(self.toggle_sounds)
        self.sound = 'beep'

        self.volumeGroup = QtGui.QActionGroup(self.menuVolume)
        self.volumeGroup.setExclusive(True)
        self.actionHigh.setActionGroup(self.volumeGroup)
        self.actionHigh.triggered.connect(self.toggle_volume)
        self.actionMedium.setActionGroup(self.volumeGroup)
        self.actionMedium.triggered.connect(self.toggle_volume)
        self.actionLow.setActionGroup(self.volumeGroup)
        self.actionLow.triggered.connect(self.toggle_volume)
        self.volume = 1
Beispiel #2
0
 def _center_widget(self, widget):
     w = QtGui.QWidget(self)
     hbox = QtGui.QHBoxLayout(w)
     hbox.setAlignment(QtCore.Qt.AlignCenter)
     hbox.setContentsMargins(0, 0, 0, 0)
     hbox.addWidget(widget)
     return w
 def _update_meanmap_transform(self):
     translate_transform = QtGui.QTransform().translate(
         self.mm_ymin, self.mm_xmin)
     scale_transform = QtGui.QTransform().scale(self.mm_dy, self.mm_dx)
     transpose_transform = QtGui.QTransform()
     transpose_transform *= QtGui.QTransform(0, 1, 0, 1, 0, 0, 0, 0, 1)
     self.meanmap_transform = scale_transform * translate_transform * transpose_transform
Beispiel #4
0
 def _set_subscription(self, source, title, value):
     for row in range(0, self.table.rowCount()):
         if (self.table.item(row, 0).text() == source.name()
                 and self.table.item(row, 1).text() == title):
             if (value):
                 brush = QtGui.QBrush(QtGui.QColor(230, 255, 230))
             else:
                 brush = QtGui.QBrush()
             for column in range(0, self.table.columnCount()):
                 self.table.item(row, column).setBackground(brush)
    def _image_transform(self, img, source, title):
        """Returns the appropriate transform for the content"""
        conf = source.conf[title]

        xmin = conf.get('xmin', 0)
        ymin = conf.get('ymin', 0)

        xmax = img.shape[-1] + xmin
        ymax = img.shape[-2] + ymin
        if "xmax" in conf:
            if (conf['xmax'] <= xmin):
                logging.warning(
                    "xmax <= xmin for title %s on %s. Ignoring xmax", title,
                    source.name())
            else:
                xmax = conf['xmax']
        if "ymax" in conf:
            if (conf['ymax'] <= ymin):
                logging.warning(
                    "ymax <= ymin for title %s on %s. Ignoring xmax", title,
                    source.name())
            else:
                ymax = conf['ymax']

        translate_transform = QtGui.QTransform().translate(ymin, xmin)

        # The order of dimensions in the scale call is (y,x) as in the numpy
        # array the last dimension corresponds to the x.
        scale_transform = QtGui.QTransform().scale(
            (ymax - ymin) / img.shape[-2], (xmax - xmin) / img.shape[-1])

        #rotate_transform = QtGui.QTransform()
        #if source.data_type[title] == 'image':
        #    if "angle" in conf:
        #        rotate_transform = QtGui.QTransform(numpy.cos(conf["angle"]), numpy.sin(conf["angle"]), -numpy.sin(conf["angle"]), numpy.cos(conf["angle"]), 0, 0)

        transpose_transform = QtGui.QTransform()
        if source.data_type[title] == 'image':
            transpose_transform *= QtGui.QTransform(0, 1, 0, 1, 0, 0, 0, 0, 1)
        if (self.settingsWidget.ui.transpose.currentText() == 'Yes'
                or (self.settingsWidget.ui.transpose.currentText() == 'Auto'
                    and "transpose" in conf)):
            transpose_transform *= QtGui.QTransform(0, 1, 0, 1, 0, 0, 0, 0, 1)

        transform = scale_transform * translate_transform * transpose_transform
        #transform = scale_transform * translate_transform * rotate_transform * transpose_transform

        # print '|%f %f %f|' % (transform.m11(), transform.m12(), transform.m13())
        # print '|%f %f %f|' % (transform.m21(), transform.m22(), transform.m23())
        # print '|%f %f %f|' % (transform.m31(), transform.m32(), transform.m33())
        return transform
Beispiel #6
0
    def add_row(self, source, plotdata, row=None):
        if row is None:
            row = self.table.rowCount()
        self.table.insertRow(row)
        item = QtGui.QTableWidgetItem(source.name())
        item.setData(QtCore.Qt.UserRole, source)
        item.setFlags(item.flags() & ~QtCore.Qt.ItemIsEditable)
        self.table.setItem(row, 0, item)
        item = QtGui.QTableWidgetItem(plotdata.title)
        item.setData(QtCore.Qt.UserRole, plotdata)
        item.setFlags(item.flags() & ~QtCore.Qt.ItemIsEditable)
        self.table.setItem(row, 1, item)
        bar = QtGui.QProgressBar()
        self.table.setItem(row, 2, QtGui.QTableWidgetItem())
        self.table.setCellWidget(row, 2, self._center_widget(bar))
        checkbox = QtGui.QCheckBox()
        checkbox.setChecked(plotdata.restored)
        self.table.setItem(row, 3, QtGui.QTableWidgetItem())
        self.table.setCellWidget(row, 3, self._center_widget(checkbox))
        checkbox = QtGui.QCheckBox()
        checkbox.setEnabled(plotdata.ishistory)
        checkbox.setChecked(plotdata.recordhistory)
        self.table.setItem(row, 4, QtGui.QTableWidgetItem())
        self.table.setCellWidget(row, 4, self._center_widget(checkbox))

        # Mark existing subscriptions
        if (plotdata.title in source.subscribed_titles):
            self._set_subscription(source, plotdata.title, True)
 def _finish_layout(self):
     """This is called after the derived classes finish settings up so
     that the lower common section of the window can be setup. Kinda ugly."""
     layout = QtGui.QVBoxLayout(self.plotFrame)
     layout.addWidget(self.plot)
     self.plot_title = str(self.title.text())
     self.title.textChanged.connect(self._on_title_change)
Beispiel #8
0
 def add_backend(self, data_source):
     """Add backend to menu if it's not there yet
     and append to _data_sources"""
     actions = self._backends_menu.actions()
     unique = True
     for a in actions:
         if (a.text() == data_source.name()):
             unique = False
     if (not unique):
         QtGui.QMessageBox.warning(
             self, "Duplicate backend",
             "Duplicate backend. Ignoring %s" % data_source.name())
         return
     self._data_sources.append(data_source)
     logging.debug("Registering data source '%s' in the GUI",
                   data_source.name())
     action = QtGui.QAction(data_source.name(), self)
     action.setData(data_source)
     action.setCheckable(True)
     action.setChecked(True)
     self._backends_menu.addAction(action)
     action.triggered.connect(self._data_source_triggered)
     self.plotdata_widget.add_source(data_source)
     data_source._recorder = self._recorder
     self._status_message("Backend '%s' connected." % (data_source.name()),
                          5000)
Beispiel #9
0
 def _setup_connections(self):
     """Initialize connections"""
     self.menuData_Sources.aboutToShow.connect(self.on_menu_show)
     self.actionSaveToPNG.triggered.connect(self.on_save_to_png)
     self.actionSaveToPNG.setShortcut(QtGui.QKeySequence("Ctrl+P"))
     self.actionSound_on_off.triggered.connect(self.toggle_alert)
     self.alertBlinkTimer.timeout.connect(self.blink_alert)
 def _setup_connections(self):
     """Initialize connections"""
     self.menuData_Sources.aboutToShow.connect(self.on_menu_show)
     self.actionSaveToPNG.triggered.connect(self.on_save_to_png)
     self.actionSaveToPNG.setShortcut(QtGui.QKeySequence("Ctrl+P"))
     self.alertBlinkTimer.timeout.connect(self.blink_alert)
     self.title.installEventFilter(self)
     self.timeLabel.installEventFilter(self)
     self.dateLabel.installEventFilter(self)
 def add_menu(title, menu, ds):
     action = QtGui.QAction(title, self)
     action.setData([ds, title])
     action.setCheckable(True)
     if (ds in self._enabled_sources
             and title in self._enabled_sources[ds]):
         action.setChecked(True)
     else:
         action.setChecked(False)
     menu.addAction(action)
     action.triggered.connect(self._source_title_triggered)
Beispiel #12
0
def start_interface(restore):
    """Initialize and show the Interface"""
    # Catch Ctrl+c and such
    signal.signal(signal.SIGINT, sigint_handler)
    QtCore.QCoreApplication.setOrganizationName("SPI")
    QtCore.QCoreApplication.setOrganizationDomain("spidocs.rtfd.org")
    QtCore.QCoreApplication.setApplicationName("Hummingbird")
    app = QtGui.QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(True)
    GUI(restore).show()
    sys.exit(app.exec_())
    def updateFonts(self):
        f = self.title.font()
        size = int(self.settings.value("plotFontSize"))
        f.setPointSize(size)
        self.title.setFont(f)

        f = QtGui.QFont()
        f.setPointSize(size)
        ax = self.plot.getAxis('left')
        ax.setTickFont(f)
        ax = self.plot.getAxis('bottom')
        ax.setTickFont(f)
Beispiel #14
0
 def add_header(self, name, row=None):
     if row is None:
         row = self.table.rowCount()
     self.table.insertRow(row)
     named_item = QtGui.QTableWidgetItem(name)
     named_item.setFlags(QtCore.Qt.NoItemFlags)
     header_font = QtGui.QFont()
     header_font.setBold(True)
     named_item.setFont(header_font)
     named_item.setData(QtCore.Qt.UserRole, str(name))
     self.table.setItem(row, 1, named_item)
     separator_text = ""
     item = QtGui.QTableWidgetItem(separator_text)
     item.setFlags(QtCore.Qt.NoItemFlags)
     self.table.setItem(row, 0, item)
     item = QtGui.QTableWidgetItem(separator_text)
     item.setFlags(QtCore.Qt.NoItemFlags)
     self.table.setItem(row, 2, item)
     item = QtGui.QTableWidgetItem(separator_text)
     item.setFlags(QtCore.Qt.NoItemFlags)
     self.table.setItem(row, 3, item)
     item = QtGui.QTableWidgetItem(separator_text)
     item.setFlags(QtCore.Qt.NoItemFlags)
     self.table.setItem(row, 4, item)
     return named_item
Beispiel #15
0
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        label = QtGui.QLabel('<center><b>Data Sources</b></center>')
        vbox = QtGui.QVBoxLayout(self)
        vbox.addWidget(label)

        self.table = QtGui.QTableWidget()
        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels([
            'Backend', 'Title', 'Buffer Capacity', 'Save on Exit',
            'Record History'
        ])
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().setHighlightSections(False)
        self.table.verticalHeader().hide()
        self.table.setShowGrid(False)
        self.table.setAlternatingRowColors(True)
        self.table.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
        self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.table.itemSelectionChanged.connect(self._on_selection_changed)

        self._groups = {None: [[], None]}

        vbox.addWidget(self.table)
        hbox = QtGui.QHBoxLayout()
        hbox.addStretch()
        self.clear_buffer = QtGui.QPushButton('Clear Buffer', self)
        self.clear_buffer.setEnabled(False)
        self.clear_buffer.clicked.connect(self._on_clear_buffer_clicked)
        hbox.addWidget(self.clear_buffer)
        self.buffer_size = QtGui.QPushButton('Set Buffer Capacity', self)
        self.buffer_size.setEnabled(False)
        self.buffer_size.clicked.connect(self._on_buffer_size_clicked)
        hbox.addWidget(self.buffer_size)
        self.buffer_spin = QtGui.QSpinBox(self)
        self.buffer_spin.setEnabled(False)
        self.buffer_spin.setMaximum(1024 * 1024 * 1024)
        hbox.addWidget(self.buffer_spin)
        hbox.addStretch()
        vbox.addLayout(hbox)
    def replot(self):
        """Replot data"""

        for source, title in self.source_and_titles():
            if (title not in source.plotdata):
                continue
            pd = source.plotdata[title]
            if (pd.y is None or len(pd.y) == 0):
                continue

            conf = source.conf[title]
            if "alert" in conf and self.alert and conf['alert']:
                os.system('afplay -v %f src/interface/ui/sounds/%s.wav &' %
                          (self.volume, self.sound))
                if not self.alertBlinkTimer.isActive():
                    self.alertBlinkTimer.start()
            else:
                if self.alertBlinkTimer.isActive():
                    self.alertBlinkTimer.stop()
                    self.setStyleSheet("")

            if (self.settingsWidget.ui.ignore_source.isChecked() is False):
                if 'vmin' in conf and conf['vmin'] is not None:
                    cmin = self.settingsWidget.ui.colormap_min
                    cmin.setText(str(conf['vmin']))
                if 'vmax' in conf and conf['vmax'] is not None:
                    cmax = self.settingsWidget.ui.colormap_max
                    cmax.setText(str(conf['vmax']))
                if 'vmin' in conf or 'vmax' in conf:
                    self.set_colormap_range()

            if conf["data_type"] == "running_hist":
                if not self.running_hist_initialised:
                    self.init_running_hist(source, title)
                window = int(self.settingsWidget.ui.runningHistWindow.text())
                bins = int(self.settingsWidget.ui.runningHistBins.text())
                hmin = int(self.settingsWidget.ui.runningHistMin.text())
                hmax = int(self.settingsWidget.ui.runningHistMax.text())
                v = pd.y[-1]
                length = pd.maxlen
                img = utils.array.runningHistogram(v, title, length, window,
                                                   bins, hmin, hmax)
                if not img.shape[0]:
                    continue
            else:
                img = numpy.array(pd.y, copy=False)
            self._configure_axis(source, title)
            transform = self._image_transform(img, source, title)

            if conf["data_type"] == "running_hist":
                translate_transform = QtGui.QTransform().translate(0, hmin)
                scale_transform = QtGui.QTransform().scale(
                    3. * float(hmax - hmin) / float(length),
                    float(hmax - hmin) / float(bins))
                transform = scale_transform * translate_transform

            if (self.plot.image is None or  # Plot if first image
                    len(self.plot.image.shape) < 3
                    or  # Plot if there's no history
                    self.plot.image.shape[0] - 1 == self.plot.currentIndex
                ):  # Plot if we're at the last image in history
                auto_levels = False
                auto_range = False
                auto_histogram = False
                if (self.plot.image is None and self.restored == False):
                    # Turn on auto on the first image
                    auto_levels = True
                    auto_rage = True
                    auto_histogram = True
                if "data_type" in conf and conf["data_type"] == "triple":
                    triples = numpy.array(pd.y, copy=False)
                    times = numpy.array(pd.x, copy=False)
                    img, transform, x, y = self._fill_meanmap(
                        times,
                        triples,
                        xmin=conf["xmin"],
                        xmax=conf["xmax"],
                        ymin=conf["ymin"],
                        ymax=conf["ymax"],
                        ybins=conf["ybins"],
                        xbins=conf["xbins"],
                        dynamic_extent=conf.get("dynamic_extent", False),
                        initial_reset=conf.get("initial_reset", False),
                    )
                else:
                    x, y = (0, 0)
                if (self.settingsWidget.ui.show_trend.isChecked()):
                    _trend = getattr(
                        numpy,
                        str(self.settingsWidget.ui.trend_options.currentText())
                    )
                    img = _trend(img, axis=0)

                if self.settingsWidget.ui.modelVisibility.value() > 0:
                    # We should overwrite part of the image with a model
                    dirty = False
                    centerx = float(self.settingsWidget.ui.modelCenterX.text())
                    if 'centerx' not in self.modelParameters or centerx != self.modelParameters[
                            'centerx']:
                        dirty = True
                        self.modelParameters['centerx'] = centerx

                    centery = float(self.settingsWidget.ui.modelCenterY.text())
                    if 'centery' not in self.modelParameters or centery != self.modelParameters[
                            'centery']:
                        dirty = True
                        self.modelParameters['centery'] = centery

                    diameter = float(
                        self.settingsWidget.ui.modelDiameter.text()) * 1e-9
                    if 'diameter' not in self.modelParameters or diameter != self.modelParameters[
                            'diameter']:
                        dirty = True
                        self.modelParameters['diameter'] = diameter

                    intensity = float(self.settingsWidget.ui.pulseIntensity.
                                      text()) * 1e-3 / 1e-12
                    if 'intensity' not in self.modelParameters or intensity != self.modelParameters[
                            'intensity']:
                        dirty = True
                        self.modelParameters['intensity'] = intensity

                    wavelength = 1239.84193 / float(
                        self.settingsWidget.ui.photonEnergy.text()) * 1e-9
                    if 'wavelength' not in self.modelParameters or wavelength != self.modelParameters[
                            'wavelength']:
                        dirty = True
                        self.modelParameters['wavelength'] = wavelength

                    distance = float(
                        self.settingsWidget.ui.detectorDistance.text())
                    if 'distance' not in self.modelParameters or distance != self.modelParameters[
                            'distance']:
                        dirty = True
                        self.modelParameters['distance'] = distance

                    pixelsize = float(
                        self.settingsWidget.ui.detectorPixelSize.text()) * 1e-6
                    if 'pixelsize' not in self.modelParameters or pixelsize != self.modelParameters[
                            'pixelsize']:
                        dirty = True
                        self.modelParameters['pixelsize'] = pixelsize

                    if dirty:
                        material = 'virus'
                        quantum_efficiency = 1.0
                        adu_per_photon = float(
                            self.settingsWidget.ui.detectorGain.text()
                        ) / float(
                            self.settingsWidget.ui.photonEnergy.text()) * 1e3
                        self.modelParameters['adu_per_photon'] = adu_per_photon
                        size = self.spimage.sphere_model_convert_diameter_to_size(
                            diameter, wavelength, pixelsize, distance)
                        scaling = self.spimage.sphere_model_convert_intensity_to_scaling(
                            intensity, diameter, wavelength, pixelsize,
                            distance, quantum_efficiency, adu_per_photon,
                            material)
                        fit = self.spimage.I_sphere_diffraction(
                            scaling,
                            self.spimage.rgrid(img[0].shape,
                                               (centerx, centery)), size)
                        self.modelParameters['fit'] = fit
                    else:
                        fit = self.modelParameters['fit']
                        adu_per_photon = self.modelParameters['adu_per_photon']

                    extent = numpy.ceil(
                        img.shape[2] *
                        self.settingsWidget.ui.modelVisibility.value() / 100.0)
                    if self.settingsWidget.ui.modelPoisson.isChecked():
                        fit = numpy.random.poisson(
                            fit[:, :extent] / adu_per_photon) * adu_per_photon
                    else:
                        fit = fit[:, :extent]
                    img[-1, :, :extent] = fit

                self.plot.setImage(img,
                                   transform=transform,
                                   autoRange=auto_range,
                                   autoLevels=auto_levels,
                                   autoHistogramRange=auto_histogram)

                self._show_crosshair(x, y)
                if (len(self.plot.image.shape) > 2):
                    # Make sure to go to the last image
                    last_index = self.plot.image.shape[0] - 1
                    self.plot.setCurrentIndex(
                        last_index, autoHistogramRange=auto_histogram)
                self._set_logscale(source, title)

            self.setWindowTitle(pd.title)
            dt, msg = self.get_time_and_msg()
            self.infoLabel.setText(msg)
            # Round to miliseconds
            self.timeLabel.setText(
                '%02d:%02d:%02d.%03d' %
                (dt.hour, dt.minute, dt.second, dt.microsecond / 1000))
            self.dateLabel.setText(str(dt.date()))
    def __init__(self, parent=None):
        # This also sets up the UI part
        DataWindow.__init__(self, parent)
        # This is imported here to prevent problems with sphinx
        from .image_view import ImageView
        self.plot = ImageView(self, view=pyqtgraph.PlotItem())
        self._finish_layout()
        self.infoLabel.setText('')
        self.acceptable_data_types = [
            'image', 'vector', 'triple', 'running_hist'
        ]
        self.exclusive_source = True
        self.meanmap = None
        self.last_x = None
        self.last_y = None
        self.mm_last = None
        self.vline = None
        self.hline = None

        self.settingsWidget.setVisible(self.actionPlotSettings.isChecked())
        self.settingsWidget.ui.colormap_min.editingFinished.connect(
            self.set_colormap_range)
        self.settingsWidget.ui.colormap_max.editingFinished.connect(
            self.set_colormap_range)
        self.settingsWidget.ui.colormap_min.setValidator(
            QtGui.QDoubleValidator())
        self.settingsWidget.ui.colormap_max.setValidator(
            QtGui.QDoubleValidator())
        self.settingsWidget.ui.colormap_full_range.clicked.connect(
            self.set_colormap_full_range)

        self.settingsWidget.ui.histogram_show.toggled.connect(
            self.plot.getHistogramWidget().setVisible)
        self.actionHistogram.triggered.connect(
            self.plot.getHistogramWidget().setVisible)
        self.actionHistogram.triggered.connect(
            self.settingsWidget.ui.histogram_show.setChecked)
        self.settingsWidget.ui.histogram_show.toggled.connect(
            self.actionHistogram.setChecked)

        self.settingsWidget.ui.x_show.toggled.connect(self.toggle_axis)
        self.actionX_axis.triggered.connect(self.toggle_axis)
        self.settingsWidget.ui.y_show.toggled.connect(self.toggle_axis)
        self.actionY_axis.triggered.connect(self.toggle_axis)
        self.settingsWidget.ui.histogram_show.toggled.connect(self.toggle_axis)
        self.actionHistogram.triggered.connect(self.toggle_axis)

        self.settingsWidget.ui.modelCenterX.setValidator(
            QtGui.QDoubleValidator())
        self.settingsWidget.ui.modelCenterY.setValidator(
            QtGui.QDoubleValidator())
        self.settingsWidget.ui.modelDiameter.setValidator(
            QtGui.QDoubleValidator())
        self.settingsWidget.ui.photonEnergy.setValidator(
            QtGui.QDoubleValidator())
        self.settingsWidget.ui.detectorGain.setValidator(
            QtGui.QDoubleValidator())
        self.settingsWidget.ui.detectorDistance.setValidator(
            QtGui.QDoubleValidator())
        self.settingsWidget.ui.detectorPixelSize.setValidator(
            QtGui.QDoubleValidator())
        self.modelParameters = {}

        success, spimage = utils.io.load_spimage()
        if not success:
            # no spimage available, we need to disable the model settings
            self.settingsWidget.ui.modelTab.setEnabled(False)
        else:
            self.spimage = spimage

        self.settingsWidget.ui.colormap_max.setValidator(
            QtGui.QDoubleValidator())

        self.plot.getHistogramWidget().region.sigRegionChangeFinished.connect(
            self.set_colormap_range)
        self.actionPlotSettings.triggered.connect(self.toggle_settings)

        # Make sure to disable native menus
        self.plot.getView().setMenuEnabled(False)
        self.plot.getHistogramWidget().vb.setMenuEnabled(False)
        self.x_axis_name = 'left'
        self.y_axis_name = 'bottom'
        self._set_logscale_lookuptable()

        self.running_hist_initialised = False

        self.actionReset_cache.triggered.connect(self.on_reset_cache)