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
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
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
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)
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)
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)
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)
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
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)