ソースを参照

Two Pages

Controlpart and Multiwindowpart are now in a two page scheme organized.
Page Change is not the best -> Better solution is required
Patrick Schreiber 9 年 前
コミット
d650620a04
6 ファイル変更304 行追加53 行削除
  1. 3 3
      README.md
  2. 161 1
      base/controlwidget.py
  3. 42 12
      base/kcg.py
  4. 18 7
      base/kcgwidget.py
  5. 25 18
      base/leftbar.py
  6. 55 12
      base/plotWidget.py

+ 3 - 3
README.md

@@ -1,4 +1,4 @@
-KCG
-===
+KCG - KAPTURE Control Gui
+=========================
 
-Development Repository of the new KAPTURE Gui
+Development Repository of the new Gui of the KAPTURE-Readout-Board

+ 161 - 1
base/controlwidget.py

@@ -1 +1,161 @@
-__author__ = 'blaxxun'
+from PyQt4 import QtGui, QtCore
+import logging
+
+import kcgwidget as kcgw
+
+# class StatusLED(QtGui.QWidget):
+#     def __init__(self, status):
+#         super(StatusLED, self).__init__()
+#         self.pixmap_on = QtGui.QPixmap('images/led_on.jpg')
+#         self.pixmap_off = QtGui.QPixmap('images/led_off.jpg')
+#         self.led = QtGui.QLabel()
+#         if status:
+#             self.set_on()
+#         else:
+#             self.set_off()
+#     def set_on(self):
+#         self.led.setPixmap(self.pixmap_on)
+#     def set_off(self):
+#         self.led.setPixmap(self.pixmap_off)
+
+class LED(QtGui.QWidget):
+
+    def __init__(self, parent=None, status=None, height=10, width=10):
+        QtGui.QWidget.__init__(self, parent)
+        colorRGB=(255, 0, 0)
+        self.width = width
+        self.height = height
+        self.color = QtGui.QColor(colorRGB[0], colorRGB[1], colorRGB[2])
+        self.center = QtCore.QPoint(width, height)
+        self.setMinimumSize(2 * width, 2 * height)
+        self.setMaximumSize(2 * width, 2 * height)
+        if status:
+            self.set_on()
+        elif status == False:
+            self.set_off()
+        else:
+            self.set_out()
+        self.status = status
+
+    def paintEvent(self, event):
+        paint = QtGui.QPainter()
+        paint.begin(self)
+        paint.setRenderHint(QtGui.QPainter.Antialiasing)
+
+        # draw a grey 'socket' for the LED
+        paint.setPen(QtGui.QColor(160, 160, 160))
+        paint.setBrush(QtGui.QColor(180, 180, 180))
+        paint.drawEllipse(self.center, self.width, self.height)
+
+        # draw the body of the LED
+        paint.setBrush(self.color)
+        paint.drawEllipse(self.center, self.width*0.85, self.height*0.85)
+
+    def set_on(self):
+        self.color = QtGui.QColor(0, 255, 0)
+        self.update()
+        self.status = True
+    def set_off(self):
+        self.color = QtGui.QColor(255, 0, 0)
+        self.update()
+        self.status = False
+    def set_out(self):
+        self.color = QtGui.QColor(150, 150, 150)
+        self.update()
+        self.status = None
+
+class StatusLED(QtGui.QWidget):
+    def __init__(self, text, status=None):
+        super(StatusLED, self).__init__()
+        self.layout = QtGui.QHBoxLayout()
+        self.label = QtGui.QLabel(text)
+        self.led = LED(status=status, width=9, height=9)
+        self.layout.addWidget(self.led)
+        self.layout.addWidget(self.label)
+        self.setLayout(self.layout)
+    def set_on(self):
+        self.led.set_on()
+    def set_off(self):
+        self.led.set_off()
+    def set_out(self):
+        self.led.set_out()
+    def toggle(self):
+        if self.led.status:
+            self.led.set_off()
+        elif self.led.status == False:
+            self.led.set_on()
+        else:
+            self.led.set_on()
+
+class LogHandler(logging.Handler):
+    def __init__(self, log_area):
+        logging.Handler.__init__(self)
+        self.text_area = log_area
+
+    def emit(self, record):
+        self.text_area.append(self.format(record))
+
+
+
+class ControlWidget(kcgw.KCGWidgets):
+    def __init__(self):
+        super(ControlWidget, self).__init__()
+
+        self.initUi()
+
+    def dummy_button_press_function(self, w=None):
+        logging.info("Button Pressed - {}".format(w))
+    def initUi(self):
+        self.overlayout = QtGui.QVBoxLayout()
+        self.setLayout(self.overlayout)
+        self.layout = QtGui.QHBoxLayout()
+        self.overlayout.addLayout(self.layout)
+        self.overlayout.addStretch(1)
+
+        self.gridLayout = QtGui.QGridLayout()
+        self.gridLayout.addWidget(self.createLabel("Board Control"), 0, 0)
+        self.gridLayout.addWidget(self.createLabel("Board Status"), 0, 1)
+
+        # LED Status
+        self.pipeline_led = StatusLED("DataFlow Pipeline")
+        self.master_control_led = StatusLED("Master Control")
+        self.data_check_led = StatusLED("Data Check")
+        self.pll_ld_led = StatusLED("PLL_LD")
+        self.gridLayout.addWidget(self.pipeline_led, 1, 1)
+        self.gridLayout.addWidget(self.master_control_led, 2, 1)
+        self.gridLayout.addWidget(self.data_check_led, 3, 1)
+        self.gridLayout.addWidget(self.pll_ld_led, 4, 1)
+
+        # Buttons
+        self.gridLayout.addWidget(self.createButton(text="Start Board", connect=lambda: self.dummy_button_press_function(1)), 1, 0)
+        self.gridLayout.addWidget(self.createButton(text="Calibrate", connect=lambda: self.dummy_button_press_function(2)), 2, 0)
+        self.gridLayout.addWidget(self.createButton(text="Synchronize", connect=lambda: self.dummy_button_press_function(3)), 3, 0)
+        self.gridLayout.addWidget(self.createButton(text="Set Defaults", connect=lambda: self.dummy_button_press_function(4)), 4, 0)
+        self.gridLayout.addWidget(self.createButton(text="Soft Reset", connect=lambda: self.dummy_button_press_function(5)), 5, 0)
+        self.gridLayout.addWidget(self.createButton(text="Board Off", connect=lambda: self.dummy_button_press_function(6)), 6, 0)
+        self.gridLayout.addWidget(self.createButton(text="Check Status", connect=self.on_check), 5, 1)
+
+
+        self.layout.addLayout(self.gridLayout)
+        self.layout.addStretch(1)
+        self.log_area = QtGui.QTextEdit()
+        self.log_area.setReadOnly(True)
+        self.overlayout.addWidget(self.log_area)
+
+        # Logging
+        log_handler = LogHandler(self.log_area)
+        log_handler.setFormatter(logging.Formatter('%(asctime)s - %(funcName)s(): %(message)s'))
+        self.logger = logging.getLogger()
+        self.logger.addHandler(log_handler)
+        self.logger.setLevel(logging.INFO)
+
+    def on_check(self):
+        import random
+        r = [random.random()+0.5 for i in range(4)]
+        ledlist = [self.pipeline_led, self.master_control_led, self.data_check_led, self.pll_ld_led]
+        for i, led in enumerate(ledlist):
+            if int(r[i]) == 1:
+                led.set_on()
+            else:
+                led.set_off()
+        logging.info("Checked: {}".format(str([int(i) for i in r])))

+ 42 - 12
base/kcg.py

@@ -1,8 +1,10 @@
 from PyQt4 import QtGui, QtCore
 import numpy as np
+import pyqtgraph as pg
 
 import kcgwidget as kcgw
 from leftbar import LeftBar
+from controlwidget import ControlWidget
 
 class IdGenerator():
     highest_id = 0
@@ -33,24 +35,52 @@ class MDIArea(kcgw.KCGWidgets):
         subWidget.show()
 
 
-class CentralWidget(QtGui.QWidget):
+class CentralWidget(kcgw.KCGWidgets):
     def __init__(self):
         super(CentralWidget, self).__init__()
 
         self.initUI()
 
     def initUI(self):
-        self.layout = QtGui.QHBoxLayout(self)
-        self.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
-
-        self.leftBar = LeftBar(self)
-        self.area = MDIArea(self)
-
-        self.splitter.addWidget(self.leftBar)
-        self.splitter.addWidget(self.area.area)
-
-        self.layout.addWidget(self.splitter)
+        self.layout = QtGui.QVBoxLayout()
+        self.sWidget = QtGui.QStackedWidget()
+        self.layout.addWidget(self.sWidget)
         self.setLayout(self.layout)
+        self.cWidget()
+        self.mWidget()
+        self.sWidget.addWidget(self.controlWidget)
+        self.sWidget.addWidget(self.multiWidget)
+        self.sWidget.setCurrentIndex(0)
+        self.leftLabel.clicked.connect(lambda: self.sWidget.setCurrentIndex(0))
+        self.rightLabel.clicked.connect(lambda: self.sWidget.setCurrentIndex(1))
+    def cWidget(self):
+        self.controlWidget = kcgw.KCGWidgets()
+        self.controlWidget.layout = QtGui.QHBoxLayout()
+
+        self.rightLabel = self.createLabel(">", click=True)
+        self.rightLabel.setFixedWidth(20)
+
+        self.mainControlWidget = ControlWidget()
+        self.controlWidget.layout.addWidget(self.mainControlWidget)
+        self.controlWidget.layout.addWidget(self.rightLabel)
+        self.controlWidget.setLayout(self.controlWidget.layout)
+
+    def mWidget(self):
+        self.multiWidget = QtGui.QWidget()
+        self.multiWidget.layout = QtGui.QHBoxLayout(self.multiWidget)
+        self.multiWidget.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
+
+        self.multiWidget.leftBar = LeftBar(self.multiWidget)
+        self.multiWidget.area = MDIArea(self.multiWidget)
+
+        self.multiWidget.splitter.addWidget(self.multiWidget.leftBar)
+        self.multiWidget.splitter.addWidget(self.multiWidget.area.area)
+
+        self.leftLabel = self.createLabel("<", click=True)
+        self.leftLabel.setFixedWidth(20)
+        self.multiWidget.layout.addWidget(self.leftLabel)
+        self.multiWidget.layout.addWidget(self.multiWidget.splitter)
+        self.multiWidget.setLayout(self.multiWidget.layout)
 
 class Gui(QtGui.QMainWindow):
     def __init__(self, app):
@@ -67,7 +97,7 @@ class Gui(QtGui.QMainWindow):
         newPlotAction = QtGui.QAction("New Plot", self)
         newPlotAction.setShortcut("Ctrl+N")
 
-        newPlotAction.triggered.connect(self.cw.leftBar.add_plot)
+        newPlotAction.triggered.connect(self.cw.multiWidget.leftBar.add_plot)
 
         self.fileMenu = self.menu.addMenu("&File")
         self.fileMenu.addAction(newPlotAction)

+ 18 - 7
base/kcgwidget.py

@@ -3,9 +3,14 @@ Class containing the creators for buttons etc
 """
 from PyQt4 import QtGui, QtCore
 
-#mainStorage = None
 idg = None
 
+class clickLabel(QtGui.QLabel):
+    clicked = QtCore.pyqtSignal()
+    def mousePressEvent(self, QMouseEvent):
+        self.clicked.emit()
+
+
 class KCGWidgets(QtGui.QWidget):
     def __init__(self, name=None):
         super(KCGWidgets, self).__init__()
@@ -25,7 +30,7 @@ class KCGWidgets(QtGui.QWidget):
 
     @property
     def theName(self):
-        return self._id
+        return self._name
 
     @theType.setter
     def theType(self, t):
@@ -53,8 +58,11 @@ class KCGWidgets(QtGui.QWidget):
             button.clicked.connect(connect)
         return button
 
-    def createLabel(self, text, tooltip=None):
-        label = QtGui.QLabel(self)
+    def createLabel(self, text, tooltip=None, click=False):
+        if click:
+            label = clickLabel(self)
+        else:
+            label = QtGui.QLabel(self)
         label.setText(text)
         if tooltip:
             label.setToolTip(tooltip)
@@ -85,7 +93,7 @@ class KCGSubWidget(QtGui.QMdiSubWindow):
 
     @property
     def theName(self):
-        return self._id
+        return self._name
 
     @theType.setter
     def theType(self, t):
@@ -113,8 +121,11 @@ class KCGSubWidget(QtGui.QMdiSubWindow):
             button.clicked.connect(connect)
         return button
 
-    def createLabel(self, text, tooltip=None):
-        label = QtGui.QLabel(self)
+    def createLabel(self, text, tooltip=None, vertical=False):
+        if vertical:
+            label = VerticalLabel(self)
+        else:
+            label = QtGui.QLabel(self)
         label.setText(text)
         if tooltip:
             label.setToolTip(tooltip)

+ 25 - 18
base/leftbar.py

@@ -52,7 +52,7 @@ class LeftBar(kcgw.KCGWidgets):
         self.treeWidget.resizeColumnToContents(1)
 #        self.treeWidget.header().resizeSection(0, 110)
         self.treeWidget.setHeaderHidden(True)
-        self.treeWidget.itemClicked.connect(self.print_clicked)
+        self.treeWidget.itemClicked.connect(self.plot_clicked)
         self.rootItem = self.treeWidget.invisibleRootItem()
 
         self.info = Info()
@@ -76,16 +76,16 @@ class LeftBar(kcgw.KCGWidgets):
                 trains = menu.addAction("Trains")
                 combined = menu.addAction("Combined")
 
-                heatmap.triggered.connect(lambda: self.add_plot_node(text='Heatmap', unique_id=item.uid, type=0))
-                fft.triggered.connect(lambda: self.add_plot_node(text='FFT', unique_id=item.uid, type=1))
-                trains.triggered.connect(lambda: self.add_plot_node(text='Trains', unique_id=item.uid, type=2))
-                combined.triggered.connect(lambda: self.add_plot_node(text='Combined', unique_id=item.uid, type=3))
+                heatmap.triggered.connect(lambda: self.add_plot_node(text='Heatmap', unique_id=item.uid, type=0, datatype=item.datatype))
+                fft.triggered.connect(lambda: self.add_plot_node(text='FFT', unique_id=item.uid, type=1, datatype=item.datatype))
+                trains.triggered.connect(lambda: self.add_plot_node(text='Trains', unique_id=item.uid, type=2, datatype=item.datatype))
+                combined.triggered.connect(lambda: self.add_plot_node(text='Combined', unique_id=item.uid, type=3, datatype=item.datatype))
 
                 menu.popup(pos)
         event.accept()
 
 
-    def print_clicked(self, item, i):
+    def plot_clicked(self, item, i):
         if item.is_child:
             self.openPlotWindows[item.usid].setFocus()
         else:
@@ -108,17 +108,17 @@ class LeftBar(kcgw.KCGWidgets):
 
 
     def add_plot_tree(self, text=False, unique_id=None, datatype=None):
+        if datatype == FILE:
+            fName = QtGui.QFileDialog.getOpenFileName()
+            if fName == "":
+                return
         self.openData[unique_id] = QtGui.QTreeWidgetItem()
         self.openData[unique_id].uid = unique_id
         self.openData[unique_id].is_child = False
         self.openData[unique_id].datatype = datatype
-#        self.openData[unique_id].plot_type = type
-#        for p in self.possiblePlots:
-#            twi = QtGui.QTreeWidgetItem()
-#            twi.setText(0, p)
-#            twi.setCheckState(0, QtCore.Qt.Unchecked)
-#            self.openData[unique_id].addChild(twi)
-        self.openData[unique_id].setText(0, text)
+        if datatype == FILE:
+            self.openData[unique_id].fName = fName
+        self.openData[unique_id].setText(0, "Live" if datatype == LIVE else fName.split('/')[-1])
         self.openData[unique_id].setText(1, "+")
         self.treeWidget.addTopLevelItem(self.openData[unique_id])
         self.treeWidget.expandItem(self.openData[unique_id])
@@ -126,15 +126,22 @@ class LeftBar(kcgw.KCGWidgets):
 
     def add_plot_node(self, text=False, unique_id=None, type=None, datatype=None):
         unique_sub_id = kcgw.idg.genid()
-        self.openPlotWindows[unique_sub_id] = PlotWidget(name=text, unique_id=unique_sub_id, type=type, datatype=datatype)
+        nr = self.openData[unique_id].childCount()
+        if datatype == FILE:
+            fName = self.openData[unique_id].fName
+        else:
+            fName = None
+        name = "Live" if not fName else fName.split('/')[-1]
+        self.openPlotWindows[unique_sub_id] = PlotWidget(name=name, unique_id=unique_sub_id, type=type, datatype=datatype, prefix=nr, fName=fName)
         self.openPlotWindows[unique_sub_id].close_signal.connect(lambda: self.remove_plot(unique_sub_id))
         self.openPlotWindows[unique_sub_id].change_type_signal.connect(self.update_plot)
         self.openPlotWindows[unique_sub_id].upid = unique_id
         self.parent.area.newWidget(self.openPlotWindows[unique_sub_id], name=text, unique_id=unique_sub_id, type=type)
         self.openPlots[unique_sub_id] = QtGui.QTreeWidgetItem()
-        self.openPlots[unique_sub_id].setText(0, self.possiblePlots[type])
+        self.openPlots[unique_sub_id].setText(0, self.possiblePlots[type] + " - " + str(nr))
         self.openPlots[unique_sub_id].is_child = True
         self.openPlots[unique_sub_id].usid = unique_sub_id
+        self.openPlots[unique_sub_id].nr = nr
         self.openData[unique_id].addChild(self.openPlots[unique_sub_id])
         self.treeWidget.resizeColumnToContents(0)
 
@@ -154,10 +161,12 @@ class LeftBar(kcgw.KCGWidgets):
 
     @QtCore.pyqtSlot(int, int)
     def update_plot(self, uid, type):
-        self.openPlots[uid].setText(0, self.possiblePlots[type])
+        self.openPlots[uid].setText(0, self.possiblePlots[type] + " - " + str(self.openPlots[uid].nr))
         self.treeWidget.resizeColumnToContents(0)
 
     def press_in_diag(self, value, diag=None,):
+        if diag:
+            diag.close()
         s = kcgw.idg.genid()
         if value == 1:
             self.add_plot_tree(text="Live", unique_id=s, datatype=LIVE)
@@ -165,8 +174,6 @@ class LeftBar(kcgw.KCGWidgets):
             self.add_plot_tree(text="File", unique_id=s, datatype=FILE)
         else:
             pass
-        if diag:
-            diag.close()
 
 
     def add_plot(self):

+ 55 - 12
base/plotWidget.py

@@ -9,7 +9,16 @@ import kcgwidget as kcgw
 LIVE = 1
 FILE = 2
 
+class Enum():
+    def __init__(self, *args):
+        self.idx = 0
+        for i in args:
+            setattr(self, i, self.idx)
+            self.idx += 1
+
 plotList = ["Heatmap", "FFT", "Trains", "Combined"]
+PlotType = Enum(*plotList)
+
 class SubPlotWidget(pg.PlotWidget):
     def __init__(self):
         super(SubPlotWidget, self).__init__()
@@ -42,33 +51,44 @@ class SubPlotWidget(pg.PlotWidget):
         lut = cmap.getLookupTable(0.0, 1.0, 256)
         self.img.setLookupTable(lut)
         self.img.setLevels([100, 10000])
-        self.data = [np.array([[random.random()*i*j+100 for i in xrange(int(1e3))] for j in xrange(int(1e3))]) for k in range(5)]
 
-    def plot(self, type):
+    def plot(self, data, xvalueborders=None, yvalueborders=None):
         self.i+=1
         self.i = self.i % 3
-        self.img.setImage(self.data[self.i], pos=[100, 100], scale=[10, 1/1000.])
+        self.img.setImage(data, pos=[100, 100], scale=[10, 1/1000.])
         self.img.resetTransform()
-        self.img.translate(100, 100)
-        self.plotItem.getAxis('bottom').setScale(10)
-        self.plotItem.getAxis('left').setScale(1/1000000.)
+
+        if xvalueborders:
+            self.plotItem.getAxis('bottom').setScale(xvalueborders[1]/float(data.shape[0]))
+            self.img.translate(xvalueborders[0], 0)
+
+        if yvalueborders:
+            self.img.translate(0, yvalueborders[0])
+            self.plotItem.getAxis('left').setScale(yvalueborders[1]/float(data.shape[1]))
         # self.box.autoRange(padding=0, items=[self.img])
 
 class PlotWidget(kcgw.KCGWidgets):
     close_signal = QtCore.pyqtSignal()
     change_type_signal = QtCore.pyqtSignal(int, int)
-    def __init__(self, name=None, unique_id=None, type=None, datatype=None):
+    def __init__(self, name=None, unique_id=None, type=None, datatype=None, prefix=None, fName=None):
         super(PlotWidget, self).__init__()
         if name != None:
             self.theName = name
-            self.setWindowTitle(name)
+            # self.setWindowTitle(name)
         if unique_id != None:
             self.theId = unique_id
         if type != None:
             self.theType = type
         if datatype != None:
             self.theDataType = datatype
+        if prefix != None:
+            self.thePrefix = prefix
+        if self.theDataType == FILE:
+            self.fName = fName
         self.initUI()
+        self.data = [np.array([[random.random()*i*j+100 for i in xrange(int(1e3))] for j in xrange(int(1e3))]) for k in range(5)]
+        self.i = 0
+        self.setWindowTitle(self.theName + " - " + plotList[type] + " - " + str(self.thePrefix))
         self.plot(type)
 
     def initUI(self):
@@ -88,10 +108,33 @@ class PlotWidget(kcgw.KCGWidgets):
             self.timer.start(33)
 
     def plot(self, type):
-        self.theType = type
-        self.plot_widget.plot(type=type)
-        self.setWindowTitle(plotList[type])
-        self.change_type_signal.emit(self.theId, type)
+        self.i += 1
+        self.i = self.i % 3
+        if self.theType != type:
+            self.theType = type
+            self.setWindowTitle(self.theName + " - " + plotList[type] + " - " + str(self.thePrefix))
+            self.change_type_signal.emit(self.theId, type)
+
+        if type == PlotType.FFT:
+            newData = []
+            for line in self.data[self.i].transpose():
+                newData.append(np.abs(np.fft.rfft(line)[1:]))
+            freq = np.fft.rfftfreq(self.data[self.i].shape[0])
+            self.plot_widget.plot(np.asarray(newData).transpose(), xvalueborders=(min(freq), max(freq)))
+        if type == PlotType.Heatmap:
+            self.plot_widget.plot(self.data[self.i], xvalueborders=(0, 10000), yvalueborders=(0, 0.1))
+        if type == PlotType.Trains:
+            self.plot_widget.plot(np.array([[1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]))
+        if type == PlotType.Combined:
+            self.plot_widget.plot(np.array([[0, 0, 0, 0, 0, 0, 0, 0],
+                                            [0, 0, 1, 1, 1, 1, 0, 0],
+                                            [0, 0, 1, 0, 0, 0, 0, 0],
+                                            [0, 0, 1, 0, 0, 0, 0, 0],
+                                            [0, 0, 1, 0, 0, 0, 0, 0],
+                                            [0, 0, 1, 0, 0, 0, 0, 0],
+                                            [0, 0, 1, 1, 1, 1, 0, 0],
+                                            [0, 0, 0, 0, 0, 0, 0, 0]]).transpose())
+
 
     def closeEvent(self, event):
         self.close_signal.emit()