class TimeEditWidget(QWidget): units = ('s', 'm', 'h', 'd') returnPressed = pyqtSignal() def __init__(self, parent=None): QWidget.__init__(self, parent) self.setLayout(QHBoxLayout()) self.layout().setContentsMargins(0.1, 0.1, 0.1, 0.1) self.layout().setSpacing(1) self.val = QLineEdit() self.val.setValidator(QDoubleValidator(0, 1000000, 2)) self.layout().addWidget(self.val) self.unit = QComboBox() self.unit.insertItems(0, self.units) self.layout().addWidget(self.unit) self.setValue(1) self.val.returnPressed.connect(self.on_returnPressed) self.val.editingFinished.connect(self.on_returnPressed) self.unit.currentIndexChanged.connect(self.recalcValue) def value(self): val = float(self.val.text()) current_unit_index = self.unit.currentIndex() if current_unit_index == 1: # minutes val *= 60. elif current_unit_index == 2: # hours val *= 3600. elif current_unit_index == 3: # days val *= 86400. return int(val) def setValue(self, val): fmt = '%%.%df' % self.val.validator().decimals() self.val.setText(fmt % float(val)) self.unit.setCurrentIndex(0) self.currentUnit = 0 def recalcValue(self, idx): # adjust widget value to unit unit_index_current = self.currentUnit unit_index_next = idx if unit_index_next > unit_index_current: start = unit_index_current end = unit_index_next elif unit_index_next < unit_index_current: start = unit_index_next end = unit_index_current val = float(self.val.text()) factor = 1. for i in range(start, end): if self.units[i + 1] == 'd': factor *= 24. else: factor *= 60. if unit_index_next - unit_index_current > 0: factor = 1. / factor next_value = val * factor self.val.setText('%s' % next_value) self.currentUnit = idx def on_returnPressed(self): self.returnPressed.emit()
class ToftofProfileWindow(DlgUtils, QMainWindow): def __init__(self, parent): QMainWindow.__init__(self, parent) DlgUtils.__init__(self, 'Live data') self.panel = parent layout1 = QVBoxLayout() self.plot = QwtPlot(self) layout1.addWidget(self.plot) self.curve = QwtPlotCurve() self.curve.setRenderHint(QwtPlotCurve.RenderAntialiased) self.curve.attach(self.plot) self.marker = QwtPlotMarker() self.marker.attach(self.plot) self.markerpen = QPen(Qt.red) self.marker.setSymbol( QwtSymbol(QwtSymbol.Ellipse, QBrush(), self.markerpen, QSize(7, 7))) self.zoomer = QwtPlotZoomer(self.plot.canvas()) self.zoomer.setMousePattern(QwtPlotZoomer.MouseSelect3, Qt.NoButton) self.picker = QwtPlotPicker(self.plot.canvas()) self.picker.setSelectionFlags(QwtPlotPicker.PointSelection | QwtPlotPicker.ClickSelection) self.picker.setMousePattern(QwtPlotPicker.MouseSelect1, Qt.MidButton) self.picker.selected.connect(self.pickerSelected) layout2 = QHBoxLayout() layout2.addWidget(QLabel('Scale:', self)) self.scale = QComboBox(self) self.scale.addItems([ 'Single detectors, sorted by angle', 'Scattering angle 2theta (deg)', 'Q value (A-1)' ]) self.scale.currentIndexChanged[int].connect(self.scaleChanged) layout2.addWidget(self.scale) layout2.addStretch() self.scaleframe = QFrame(self) self.scaleframe.setLayout(layout2) self.scaleframe.setVisible(False) layout1.addWidget(self.scaleframe) mainframe = QFrame(self) mainframe.setLayout(layout1) self.setCentralWidget(mainframe) self.setContentsMargins(6, 6, 6, 6) plotfont = scaledFont(self.font(), 0.7) self.plot.setAxisFont(QwtPlot.xBottom, plotfont) self.plot.setAxisFont(QwtPlot.yLeft, plotfont) self.plot.setCanvasBackground(Qt.white) self.resize(800, 200) self._detinfo = None self._anglemap = None self._infowindow = None self._infolabel = None self._xs = self._ys = None self._type = None def _retrieve_detinfo(self): if self._detinfo is None: info = self.panel.client.eval( 'det._detinfo_parsed, ' 'det._anglemap', None) if not info: return self.showError('Cannot retrieve detector info.') self._lambda = self.panel.client.eval('chWL()', None) if not self._lambda: return self.showError('Cannot retrieve wavelength.') self._detinfo, self._anglemap = info self._inverse_anglemap = 0 self._infowindow = QMainWindow(self) self._infolabel = QLabel(self._infowindow) self._infolabel.setTextFormat(Qt.RichText) self._infowindow.setCentralWidget(self._infolabel) self._infowindow.setContentsMargins(10, 10, 10, 10) self._inv_anglemap = [[ entry for entry in self._detinfo[1:] if entry[12] == self._anglemap[detnr] + 1 ][0] for detnr in range(len(self._xs))] def scaleChanged(self, scale): self.update(self._type, self._orig_nbins, self._orig_x, self._orig_y) def update(self, proftype, nbins, x, y): self._orig_x = x self._orig_y = y self._orig_nbins = nbins x.setsize(8 * nbins) y.setsize(8 * nbins) xs = struct.unpack('d' * nbins, x) ys = struct.unpack('d' * nbins, y) if proftype == 0: if self.scale.currentIndex() == 0: xs = xs elif self.scale.currentIndex() == 1: self._retrieve_detinfo() xs = [self._inv_anglemap[int(xi)][5] for xi in xs] else: self._retrieve_detinfo() if self._lambda is None: self.showError('Could not determine wavelength.') self.scale.setCurrentIndex(1) return xs = [ 4 * pi / self._lambda * sin(radians(self._inv_anglemap[int(xi)][5] / 2.)) for xi in xs ] self._xs = xs self._ys = ys self.curve.setData(xs, ys) self.plot.setAxisAutoScale(QwtPlot.xBottom) self.plot.setAxisAutoScale(QwtPlot.yLeft) self.marker.setVisible(False) self.zoomer.setZoomBase(True) self._type = proftype if proftype == 0: self.setWindowTitle( 'Single detector view (time-channel integrated)') self.scaleframe.setVisible(True) elif proftype == 1: self.setWindowTitle('Time channel view (detector integrated)') self.scaleframe.setVisible(False) else: self.scaleframe.setVisible(False) def pickerSelected(self, point): if self._type != 0: return self._retrieve_detinfo() index = self.curve.closestPoint(self.picker.transform(point))[0] detentry = self._inv_anglemap[index][:] detentry.append(self._xs[index]) detentry.append(self._ys[index]) self.marker.setXValue(self._xs[index]) self.marker.setYValue(self._ys[index]) self.marker.setVisible(True) self.plot.replot() self._infowindow.show() entrynames = [ 'EntryNr', 'Rack', 'Plate', 'Pos', 'RPos', '2Theta', 'CableNr', 'CableType', 'CableLen', 'CableEmpty', 'Card', 'Chan', 'Total', 'DetName', 'BoxNr', 'BoxChan', 'XValue', 'Counts' ] formats = [ '%s', '%d', '%d', '%d', '%d', '%.3f', '%d', '%d', '%.2f', '%d', '%d', '%d', '%d', '%r', '%d', '%d', '%s', '%d' ] empties = [1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0] self._infolabel.setText('Detector info:<br><table>' + ''.join( '<tr><td>%s</td><td></td><td>%s</td></tr>%s' % (name, format % value, '<tr></tr>' if empty else '') for (name, format, empty, value) in zip(entrynames, formats, empties, detentry)) + '</table>') def closeEvent(self, event): if self._infowindow: self._infowindow.close()