Przeglądaj źródła

Improves Color Legend

Minor Changes to other parts
Patrick Schreiber 8 lat temu
rodzic
commit
22fbf322b7
3 zmienionych plików z 125 dodań i 122 usunięć
  1. 2 2
      VERSION
  2. 6 1
      base/leftbar.py
  3. 117 119
      base/plotWidget.py

+ 2 - 2
VERSION

@@ -1,4 +1,4 @@
-0.5.0
-Date: 31.07.15
+0.5.1
+Date: 06.08.15
 
 NOTE: this program is still in beta state and may have bugs

+ 6 - 1
base/leftbar.py

@@ -272,7 +272,12 @@ class LeftBar(kcgw.KCGWidgets):
         self.treeWidget.resizeColumnToContents(0)
         self.openData[unique_id].ready = False  # indicates whether data was completely read or not
         QtGui.qApp.processEvents()
-        self.read_data(datatype, unique_id, fName if datatype == FILE else None)
+        try:
+            self.read_data(datatype, unique_id, fName if datatype == FILE else None)
+        except:
+            self.Data[unique_id] = None
+            self.remove_plot_tree(unique_id, silent=True)
+            QtGui.QMessageBox.critical(self, tr("Heading", "Error Reading Data"), tr("Dialog", "There was an error reading the datafile, make shure it is valid and try again."))
         self.openData[unique_id].ready = True # indicates whether data was completely read or not
         self.openData[unique_id].setText(1, "+")
 

+ 117 - 119
base/plotWidget.py

@@ -40,54 +40,80 @@ class ThreadFFT(Thread):
 plotList = [tr("Label", "Heatmap"), tr("Label", "FFT"), tr("Label", "Trains"), tr("Label", "Combined")]
 PlotType = Enum(*[str(i) for i in plotList])
 
+class SpectrogramColorLegendItem(pg.GraphicsWidget):
+    gradientChanged = QtCore.pyqtSignal()
+    def __init__(self, img=None):
+        super(SpectrogramColorLegendItem, self).__init__()
+        self.layout = QtGui.QGraphicsGridLayout()
+        self.setLayout(self.layout)
+        self.img = img
+        self.gei = pg.GradientEditorItem(orientation='right')
+        self.legend_axis = pg.AxisItem(orientation='left')
+        # self.addItem(self.legend_axis)
+        self.layout.addItem(self.legend_axis, 0, 0, alignment=QtCore.Qt.AlignVCenter)
+        # self.addItem(self.gei)
+        self.layout.addItem(self.gei, 0, 1)
+        self.gei.sigGradientChanged.connect(self.gradient_changed)
+        self.gei.loadPreset('spectrum')
+        # self.setFixedWidth(80)
+        self.image_changed()
+
+    def gradient_changed(self):
+        self.gradientChanged.emit()
+
+    def set_image(self, img):
+        self.img = img
+
+    def update_axis(self):
+        if self.img.getLevels():
+            min, max = self.img.getLevels()
+            self.legend_axis.setRange(min, max)
+
+    def reset_gradient(self):
+        self.gei.loadPreset('spectrum')
+
+    def image_changed(self, reset_gradient=True):
+        if self.img:
+            self.update_axis()
+            if reset_gradient:
+                self.reset_gradient()
+
+    def getLookupTable(self, nPts, alpha=None):
+        return self.gei.getLookupTable(nPts, alpha=alpha)
+
+    def resizeEvent(self, event):
+        self.legend_axis.setHeight(self.gei.length)
+
 class SubPlotWidget(pg.GraphicsLayoutWidget):
     def __init__(self):
         super(SubPlotWidget, self).__init__()
+
         # self.setStyleSheet("border: 5px solid black; margin: 10px;")
         self.plotType = 1
         self.plotItem = pg.PlotItem()
         self.img = pg.ImageItem()
-        self.hlut = pg.HistogramLUTItem(self.img, fillHistogram=True)
-        # self.grl = pg.GradientLegend((10,300), (10,30))
-        # self.img.setParentItem(self.grl)
-        # self.plotItem.addItem(self.hlut)
-        # self.plotItem.addItem(self.grl)
+
+        self.gradient_legend = SpectrogramColorLegendItem(self.img)
+        def changelut():
+            self.img.setLookupTable(self.gradient_legend.getLookupTable(512))
+        self.gradient_legend.gradientChanged.connect(changelut)
+
         self.addItem(self.plotItem)
         self.plotItem.addItem(self.img)
-        # self.addItem(self.hlut)
-        self.hlut.gradient.loadPreset("spectrum")
-        def doNothing(*args):
-            pass
-        # self.plotItemPlot = pg.ScatterPlotItem(pxMode=True, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 255), size=2)
-        # self.plotItemPlot.setDownsampling = doNothing
-        # self.plotItemPlot.setClipToView = doNothing
-        # self.plotItemPlot2 = pg.ScatterPlotItem(pxMode=True, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 255), size=2)
-        # self.plotItemPlot2.setDownsampling = doNothing
-        # self.plotItemPlot2.setClipToView = doNothing
-        # self.plotItemPlot3 = pg.ScatterPlotItem(pxMode=True, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 255), size=2)
-        # self.plotItemPlot3.setDownsampling = doNothingk
-        # self.plotItemPlot3.setClipToView = doNothing
         self.plotItemPlotScatter = pg.PlotDataItem(pen=None, symbolPen=pg.mkPen(50, 50, 255), symbolSize=3, pxMode=True, symbolBrush=pg.mkBrush(50, 50, 255), downsample=200)
         self.plotItemPlotScatter1 = pg.PlotDataItem(pen=None, symbolPen=pg.mkPen(255, 50, 50), symbolSize=3, pxMode=True, symbolBrush=pg.mkBrush(255, 50, 50), downsample=200)
-        self.plotItemPlotScatter2 = pg.PlotDataItem(pen=None, symbolPen=pg.mkPen(50, 255, 50), symbolSize=3, pxMode=True, symbolBrush=pg.mkBrush(50, 255, 50), downsample=200)
+        # self.plotItemPlotScatter2 = pg.PlotDataItem(pen=None, symbolPen=pg.mkPen(50, 255, 50), symbolSize=3, pxMode=True, symbolBrush=pg.mkBrush(50, 255, 50), downsample=200)
         self.plotItemPlot = pg.PlotDataItem()  # pen="#000000")
-        # self.plotItemPlot2 = pg.PlotDataItem()
-        # self.plotItemPlot3 = pg.PlotDataItem()
         self.plotItem.addItem(self.plotItemPlot)
         self.plotItem.addItem(self.plotItemPlotScatter)
         self.plotItem.addItem(self.plotItemPlotScatter1)
-        self.plotItem.addItem(self.plotItemPlotScatter2)
-        # self.plotItem.addItem(self.plotItemPlot2)
-        # self.plotItem.addItem(self.plotItemPlot3)
+        # self.plotItem.addItem(self.plotItemPlotScatter2)
 
-        self.i=0
-        pos = np.array([0, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1])
-        # color = np.array([[0, 0, 255, 255], [0, 255, 0, 255], [0, 255, 255, 255], [255, 130, 0, 255], [255, 0, 0, 255]])
-        color = np.array([[0, 0, 255, 255], [0, 255, 255, 255], [0, 255, 0, 255], [130, 255, 0, 255], [255, 255, 0, 255], [255, 180, 0, 255], [255, 100, 0, 255], [255, 0, 0, 255]])
-        cmap = pg.ColorMap(pos, color)
-        self.lut = cmap.getLookupTable(0.0, 1.0, 256)
-        self.img.setLookupTable(self.lut)
-        # self.img.setLevels([100, 10000])
+        # pos = np.array([0, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1])
+        # color = np.array([[0, 0, 255, 255], [0, 255, 255, 255], [0, 255, 0, 255], [130, 255, 0, 255], [255, 255, 0, 255], [255, 180, 0, 255], [255, 100, 0, 255], [255, 0, 0, 255]])
+        # cmap = pg.ColorMap(pos, color)
+        # self.lut = cmap.getLookupTable(0.0, 1.0, 256)
+        # self.img.setLookupTable(self.lut)
 
 
     @QtCore.pyqtSlot(np.ndarray, tuple, tuple)
@@ -95,36 +121,32 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
         self.plotItemPlot.clear()
         self.plotItemPlotScatter.clear()
         self.plotItemPlotScatter1.clear()
-        self.plotItemPlotScatter2.clear()
+        # self.plotItemPlotScatter2.clear()
         self.plotItem.resetTransform()
         self.plotItem.getAxis('bottom').setScale()
 
         if self.plotType == PlotType.FFT or self.plotType == PlotType.Heatmap:
-            self.addItem(self.hlut)
-            self.hlut.show()
-            self.hlut.autoHistogramRange()
-            self.parent().max_slider.setMinimum(np.min(data))
-            self.parent().max_slider.setMaximum(np.max(data))
-            self.parent().low_slider.setMinimum(np.min(data))
-            self.parent().low_slider.setMaximum(np.max(data))
+            self.addItem(self.gradient_legend)
+            self.gradient_legend.show()
+
+            # self.parent().max_slider.setMinimum(np.min(data))
+            # self.parent().max_slider.setMaximum(np.max(data))
+            # self.parent().low_slider.setMinimum(np.min(data))
+            # self.parent().low_slider.setMaximum(np.max(data))
 
 
             self.img.setImage(data, scale=[1, 1/1000.])
             self.img.resetTransform()
-            self.parent().max_slider.setValue(self.img.getLevels()[1])
-            self.parent().low_slider.setValue(self.img.getLevels()[0])
+            # self.parent().max_slider.setValue(self.img.getLevels()[1])
+            # self.parent().low_slider.setValue(self.img.getLevels()[0])
             self.img.setAutoDownsample(True)
             if autorange:
-                self.hlut.imageChanged(autoLevel=True)
-
-            # self.img.setLevels([, ])
+                self.gradient_legend.image_changed()
+                pass
 
             if xvalueborders:
-                # self.img.setScale(xvalueborders[1]/float(data.shape[0]))
-                # self.img.translate(xvalueborders[0], 0)
                 self.plotItem.getAxis('bottom').setScale((xvalueborders[1]-xvalueborders[0])/float(data.shape[0]))
                 self.img.translate(xvalueborders[0]/self.plotItem.getAxis('bottom').scale, 0)
-                # self.plotItem.getAxis('bottom').setTickSpacing(levels=[(1000, 0)])
 
             else:
                 self.plotItem.getAxis('bottom').setScale()
@@ -134,43 +156,31 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
                 self.plotItem.getAxis('left').setScale(yvalueborders[1]/float(data.shape[1]))
 
             self.plotItem.setClipToView(True)
-            # self.plotItem.getViewBox().autoRange()
-            # if self.plotType == PlotType.FFT:
-            #     self.img.setLevels([np.min(data), np.percentile(data, 90)])
-            # else:
-            #     self.img.setLevels([np.min(data), np.max(data)])
 
         if self.plotType == PlotType.Trains:
             self.img.clear()
-            self.hlut.hide()
+            self.gradient_legend.hide()
             try:
-                self.removeItem(self.hlut)
+                self.removeItem(self.gradient_legend)
+                pass
             except Exception, e:
                 if not "Could not determine index of item" in str(e):
                     raise
             self.plotItemPlotScatter.clear()
             self.plotItemPlotScatter1.clear()
-            self.plotItemPlotScatter2.clear()
+            # self.plotItemPlotScatter2.clear()
             self.plotItemPlot.setData(data)
-            # self.plotItemPlot.setClipToView(True)
             bounds = [np.min(data), np.max(data)]
-            self.plotItemPlot.getViewBox().setRange(xRange=[0, len(data)],
+            self.plotItemPlot.getViewBox().setRange(xRange=[0, len(data)], # Do this twice because the first wont update the image
                 yRange=[bounds[0]-0.1*(bounds[1]-bounds[1]), bounds[1]+0.1*(bounds[1]-bounds[1])], update=True)
             self.plotItemPlot.getViewBox().setRange(xRange=[0, len(data)],
                 yRange=[bounds[0]-0.1*(bounds[1]-bounds[1]), bounds[1]+0.1*(bounds[1]-bounds[1])], update=True)
-            # self.plotItem.getViewBox().setRange(yRange=[2030, 2040])
-            # self.plotItem.getAxis('left').setRange(2030, 2040)
-            # self.plotItem.setClipToView(False) # NOTE: otherwise not all lines are drawn (if the corresponding point is out of view)
-            # self.plotItem.getAxis('left').linkToView(self.plotItemPlot.getViewBox())
-            # self.plotItem.getAxis("left").range[0] = 2040
-            # self.plotItem.getAxis("left").update()
-            # self.plotItem.getViewBox().addItem(self.plotItemPlot)
-            # self.plotItem.getViewBox().autoRange()
         if self.plotType == PlotType.Combined:
             self.img.clear()
-            self.hlut.hide()
+            self.gradient_legend.hide()
             try:
-                self.removeItem(self.hlut)
+                self.removeItem(self.gradient_legend)
+                pass
             except Exception, e:
                 if not "Could not determine index of item" in str(e):
                     raise
@@ -180,7 +190,7 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
             # self.plotItemPlotScatter2.setData(data[2].transpose())  # Commented out for debug, see dataset.py combined()
             self.plotItem.setClipToView(False) # NOTE: otherwise not all lines are drawn (if the corresponding point is out of view)
         if autorange:
-            if self.plotType in [PlotType.FFT, PlotType.Heatmap]:
+            if self.plotType in [PlotType.FFT, PlotType.Heatmap, PlotType.Combined]:
                 self.plotItem.getViewBox().autoRange()
 
         self.labelAxes()
@@ -203,22 +213,16 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
 
 
     def changeType(self, type):
-        # if self.plotType == PlotType.Combined:
-            # self.plotItemPlot2.clear()
-            # self.plotItemPlot3.clear()
-            # self.plotItemPlot.clear()
         self.plotType = type
-        self.hlut.imageChanged(autoLevel=True)
+        self.gradient_legend.image_changed()
 
 class PlotWidget(kcgw.KCGWidgets):
     close_signal = QtCore.pyqtSignal()
     change_type_signal = QtCore.pyqtSignal(int, int, int)
-    fft_done_signal = QtCore.pyqtSignal(np.ndarray, tuple)
     def __init__(self, name=None, unique_id=None, type=None, datatype=None, prefix=None, fName=None, data=None):
         super(PlotWidget, self).__init__()
         if name != None:
             self.theName = name
-            # self.setWindowTitle(name)
         if unique_id != None:
             self.theId = unique_id
         if type != None:
@@ -235,14 +239,8 @@ class PlotWidget(kcgw.KCGWidgets):
             self.data = None
 
         self.adc = 1
-        self.thread = Thread()
-        self.i = 0
-        self.fft_done_signal.connect(self.fft_done)
         self.initUI()
-        # self.data = [np.array([[np.int16(np.random.random()*i*j/270.+100) for i in xrange(int(184))] for j in xrange(int(270e3))]) for k in range(1)]
-        # self.data = np.array([[np.random.randint(100, 100000, 184) for i in xrange(int(2**10))] for i in range(3)])
         self.setWindowTitle(self.theName + " - " + plotList[type] + " - " + str(self.thePrefix))
-        # self.read_data()
         self.plot_widget.changeType(type)
         if self.theDataType == FILE:
             self.plot(type)
@@ -256,24 +254,29 @@ class PlotWidget(kcgw.KCGWidgets):
         self.plot_widget = SubPlotWidget()
         self.layout = QtGui.QVBoxLayout()
         self.plot_buttons_layout = QtGui.QHBoxLayout()
+
         self.heatmap_button = self.createButton(text=tr("Button", "Heatmap"), connect=lambda: self.plot(type=0))
         self.fft_button = self.createButton(text=tr("Button", "FFT"), connect=lambda: self.plot(type=1))
         self.trains_button = self.createButton(text=tr("Button", "Trains"), connect=lambda: self.plot(type=2))
         self.combined_button = self.createButton(text=tr("Button", "Combined"), connect=lambda: self.plot(type=3))
+
         self.adc1 = self.createCheckbox(text="ADC 1", connect=self.change_adc)
         self.adc1.setChecked(True)
         self.adc2 = self.createCheckbox(text="ADC 2", connect=self.change_adc)
         self.adc3 = self.createCheckbox(text="ADC 3", connect=self.change_adc)
         self.adc4 = self.createCheckbox(text="ADC 4", connect=self.change_adc)
+
         self.plot_buttons_layout.addWidget(self.heatmap_button)
         self.plot_buttons_layout.addWidget(self.fft_button)
         self.plot_buttons_layout.addWidget(self.trains_button)
         self.plot_buttons_layout.addWidget(self.combined_button)
+
         self.adc_checkbox_layout = QtGui.QHBoxLayout()
         self.adc_checkbox_layout.addWidget(self.adc1)
         self.adc_checkbox_layout.addWidget(self.adc2)
         self.adc_checkbox_layout.addWidget(self.adc3)
         self.adc_checkbox_layout.addWidget(self.adc4)
+
         self.groupWidget = QtGui.QWidget()
         self.groupWidget.setLayout(self.adc_checkbox_layout)
         self.group = QtGui.QButtonGroup()
@@ -282,32 +285,33 @@ class PlotWidget(kcgw.KCGWidgets):
         self.group.addButton(self.adc3, 3)
         self.group.addButton(self.adc4, 4)
         self.group.setExclusive(True)
+
         self.from_to_layout = QtGui.QHBoxLayout()
         self.from_spinbox = self.createSpinbox(0, 100000000, interval=100, connect=lambda: self.plot(self.theType))
         self.to_spinbox = self.createSpinbox(0, 100000000, start_value=1000, interval=100, connect=lambda: self.plot(self.theType))
+        self.from_to_layout.addStretch()
+        self.from_to_layout.addWidget(self.createLabel(tr("Label", "From:")))
         self.from_to_layout.addWidget(self.from_spinbox)
+        self.from_to_layout.addWidget(self.createLabel(tr("Label", "To:")))
         self.from_to_layout.addWidget(self.to_spinbox)
-        self.slider_layout = QtGui.QHBoxLayout()
-        self.low_slider = QtGui.QSlider(QtCore.Qt.Horizontal)
-        self.low_slider.setMinimum(0)
-        self.low_slider.setMaximum(1000)
-        self.low_slider.valueChanged.connect(self.low_changed)
-        self.max_slider = QtGui.QSlider(QtCore.Qt.Horizontal)
-        self.max_slider.setMinimum(100)
-        self.max_slider.setMaximum(10000)
-        self.max_slider.valueChanged.connect(self.max_changed)
-        self.slider_layout.addWidget(self.low_slider)
-        self.slider_layout.addWidget(self.max_slider)
+
+        # self.slider_layout = QtGui.QHBoxLayout()
+        # self.low_slider = QtGui.QSlider(QtCore.Qt.Horizontal)
+        # self.low_slider.setMinimum(0)
+        # self.low_slider.setMaximum(1000)
+        # self.low_slider.valueChanged.connect(self.low_changed)
+        # self.max_slider = QtGui.QSlider(QtCore.Qt.Horizontal)
+        # self.max_slider.setMinimum(100)
+        # self.max_slider.setMaximum(10000)
+        # self.max_slider.valueChanged.connect(self.max_changed)
+        # self.slider_layout.addWidget(self.low_slider)
+        # self.slider_layout.addWidget(self.max_slider)
         self.layout.addLayout(self.plot_buttons_layout)
         self.layout.addWidget(self.plot_widget)
         self.layout.addWidget(self.groupWidget)
         self.layout.addLayout(self.from_to_layout)
-        self.layout.addLayout(self.slider_layout)
+        # self.layout.addLayout(self.slider_layout)
         self.setLayout(self.layout)
-        # if self.theDataType and self.theDataType == LIVE:
-        #     self.timer = QtCore.QTimer()
-        #     self.timer.timeout.connect(lambda: self.plot(self.theType))
-        #     self.timer.start(20)
     def low_changed(self, x):
         self.plot_widget.img.setLevels([x, self.max_slider.value()])
     def max_changed(self, x):
@@ -325,21 +329,23 @@ class PlotWidget(kcgw.KCGWidgets):
         self.combined_button.setDisabled(b_bool)
 
     def plot(self, type=None):
-        # try:
-        if type == None:
-            type = self.theType
-        self.do_plot(type)
-        # except Exception, e:
-        #     mb = QtGui.QMessageBox(QtGui.QMessageBox.Warning, "Error while plotting", "There was an error plotting data")
-        #     mb.exec_()
+        try:
+            if type == None:
+                type = self.theType
+            self.do_plot(type)
+        except Exception, e:
+            # mb = QtGui.QMessageBox(QtGui.QMessageBox.Warning, "Error while plotting", "There was an error plotting data")
+            QtGui.QMessageBox.critical(self, tr("Heading", "Error Plotting Data"), tr("Dialog", "There was an error plotting the data, make shure it is valid and try again."))
+            raise
+            # mb.exec_()
     def plot_live(self, type=None, data=None):
         self.data = data
-        # try:
-        if type == None:
-            type = self.theType
-        self.do_plot(type, autorange=False)
-        # except Exception, e:
-        #     print 'error during plot'
+        try:
+            if type == None:
+                type = self.theType
+            self.do_plot(type, autorange=False)
+        except Exception, e:
+            print 'error during plot'
     def do_plot(self, type, autorange=True):
         if self.theType != type:
             if type == PlotType.Combined:
@@ -356,9 +362,6 @@ class PlotWidget(kcgw.KCGWidgets):
                                                        to=self.to_spinbox.value(), drop_first_bin=True)).transpose(),
                                   autorange=autorange,
                                   xvalueborders=[self.data.fft_freq_dist(), self.data.fft_max_freq()])
-            # if not self.thread.is_alive():
-            #     self.thread = ThreadFFT(self.data[self.i], self.fft_done_signal)
-            #     self.thread.start()
         if type == PlotType.Heatmap:
             self.plot_widget.plot(self.data.heatmap(adc=self.adc, frm=self.from_spinbox.value(), to=self.to_spinbox.value()).transpose(), autorange=autorange)
         if type == PlotType.Trains:
@@ -370,13 +373,8 @@ class PlotWidget(kcgw.KCGWidgets):
     def fft_done(self, data, xborders):
         if self.theType == 1:
             self.plot_widget.plot(data, xvalueborders=xborders)
-        # self.disable_buttons(False)
 
     def closeEvent(self, event):
-        try: # if timer exists stop it
-            self.timer.stop()
-        except:
-            pass
         del self.data
         del self.plot_widget
         super(PlotWidget, self).closeEvent(event)