Browse Source

Added new FrequencyExtractWidget
Added some widgets to widgets/__init__.py

Timo Dritschler 3 years ago
parent
commit
d9bbb05ca8
2 changed files with 207 additions and 1 deletions
  1. 204 0
      KCG/widgets/FrequencyExtractWidget.py
  2. 3 1
      KCG/widgets/__init__.py

+ 204 - 0
KCG/widgets/FrequencyExtractWidget.py

@@ -0,0 +1,204 @@
+from PyQt4 import QtCore, QtGui
+
+
+from ..base import kcgwidget as kcgw
+from ..base.globals import glob as global_objects
+from ..base.backend import board
+from ..base.backend.board import available_boards
+from .. import config
+
+import pyqtgraph as pg
+from math import ceil
+import numpy as np
+
+
+
+from .PlotWidget import SubPlotWidget
+
+__widget_id__ = None
+
+
+class FrequencyExtractWidget(kcgw.KCGWidgets):
+    def __init__(self, unique_id, parent):
+        super(FrequencyExtractWidget, self).__init__()
+
+        self.id = unique_id
+        self.par = parent
+        
+        #ToDo: Maybe find valid data from the get-go?
+        self.data = None
+
+
+        self.board_config = board.get_board_config(available_boards[0]) 
+        self.board_config.observe(self, self.dataSetChanged, 'lastDataSet')
+        self.numADCs = self.board_config.get('adc_number')
+
+
+        #Use a VBox. Top half should be the SubPlotWidget, bottom
+        #half should be the controls
+        self.layout = QtGui.QVBoxLayout()
+
+        
+        self.plotBox = QtGui.QVBoxLayout()
+        self.plot = SubPlotWidget()
+
+        self.region = pg.LinearRegionItem(values=[10,20])
+        self.plot.plotItem.addItem(self.region)
+        self.region.sigRegionChangeFinished.connect(self.doPlot)
+
+        self.line = pg.InfiniteLine(angle=0, label='Y={value:0.2f}',
+                                    labelOpts={'movable': True})
+        self.plot.plotItem.addItem(self.line)
+        self.line.hide()
+
+        self.plotBox.addWidget(self.plot)
+
+
+        #Controls for the plot
+        self.controlsBox = QtGui.QHBoxLayout()
+
+        self.adcSelect = QtGui.QComboBox(self)
+        for i in range(self.numADCs):
+            self.adcSelect.addItem("ADC {}".format(i+1))
+        self.adcSelect.currentIndexChanged.connect(self.doPlot)
+
+
+        self.bucketSelect = QtGui.QComboBox(self)
+        self.bucketSelect.addItem("Mean")
+        for i in range(184):
+            self.bucketSelect.addItem("Bucket {}".format(i+1))
+        self.bucketSelect.currentIndexChanged.connect(self.doPlot)
+
+
+        self.fromBox = self.createSpinbox(0, 100000000, interval=100, connect=self.doPlot)
+        self.toBox = self.createSpinbox(0, 100000000, start_value=1000, interval=100, connect=self.doPlot)
+
+        self.controlsBox.addWidget(self.adcSelect)
+        self.controlsBox.addWidget(self.bucketSelect)
+        self.controlsBox.addStretch()
+        self.controlsBox.addWidget(self.createLabel(text="From:"))
+        self.controlsBox.addWidget(self.fromBox)
+        self.controlsBox.addWidget(self.createLabel(text="To:"))
+        self.controlsBox.addWidget(self.toBox)
+
+
+        self.frequencyTools = QtGui.QHBoxLayout()
+        
+        self.freqText = QtGui.QLineEdit(self)
+        self.isFreqValid = False
+
+        self.frequencyTools.addWidget(self.createLabel(text="Frequency:"))
+        self.frequencyTools.addWidget(self.freqText)
+
+
+        self.layout.addLayout(self.plotBox)
+        self.layout.addLayout(self.controlsBox)
+        self.layout.addLayout(self.frequencyTools)
+        self.setLayout(self.layout)
+        self.setWindowTitle("Frequency Extract")
+
+
+    def dataSetChanged(self, data=None):
+        self.data = data
+        self.doPlot()
+
+
+    def doPlot(self):
+
+        if not self.data:
+            return
+
+        #PlotWidget's "plot" function expects the fft_mode to have two entries
+        #which we don't need here. So we need to shift our index by +2 in order
+        #to accomodate for the two missing options in the bucket_select ComboBox
+        fft_mode = self.bucketSelect.currentIndex() + 2
+        adc = self.adcSelect.currentIndex()
+
+
+        self.fftData = self.data.fft(adc=self.adcSelect.currentIndex(),
+                                     frm=self.fromBox.value(),
+                                     to=self.toBox.value(),
+                                     drop_first_bin=True,
+                                     nobunching=False)
+        self.plot.plot(
+                self.fftData,
+                autorange=False,
+                xvalueborders=[self.data.fftFreqDist(), self.data.fftMaxFreq()],
+                fft_mode=fft_mode,
+                log=False)
+
+        self.plot.plotItem.setLabel('left', 'Spectral Intensity')
+
+        #I am cheating a little bit and getting the readily processed data
+        #from the plotItems, so I don't have to process, convert, format, etc.
+        #the fftData again. We already did that in the SubPlotWidget.plot
+        #function, so no need to do it again. Just steal the data from the
+        #plotItems!
+        self.fftYValues = self.plot.plotItemPlot[0].yData
+        self.fftXValues = self.plot.plotItemPlot[0].xData
+
+        region = self.region.getRegion()
+   
+        #Clip to valid data ranges
+        rLeft = ceil(region[0]) if region[0] >=0 else 0
+        rRight = ceil(region[1]) if region[1] < len(self.fftYValues) else len(self.fftYValues)
+
+        #Make sure the region is within the boundaries of our data array
+        if rLeft >= len(self.fftYValues) or rRight < 0:
+            self.freqText.setText("Region boundaries out of data range")
+            self.line.hide()
+            self.isFreqValid = False
+            self.freqText.setText("NaN")
+            return
+
+        #If the region is not really a region, ignore it
+        if rLeft == rRight:
+            self.freqText.setText("Region too small")
+            self.line.hide()
+            self.isFreqValid = False
+            self.freqText.setText("NaN")
+            return
+    
+        chunk = self.fftYValues[rLeft:rRight]
+        maxVal = np.max(chunk)
+        maxIndexInChunk = np.where(chunk == maxVal)
+
+        self.line.setValue(maxVal)
+        self.line.show()
+
+        
+        #np.where returns a tuple of indices (because it supports
+        #multidimensional arrays). But since we know that our array is only
+        #1-Dimensional, we can simply pick only the first dimension
+        maxIndexInChunk = maxIndexInChunk[0]
+        indexInData = rLeft + maxIndexInChunk
+
+        #We are basically just repeating what the plot item also did to
+        #determine the X-Axis labeling, and use it calculate the X-Value
+        #at the index we have identified
+        xAxisScale = (self.data.fftMaxFreq() - self.data.fftFreqDist()) / float(self.fftYValues.shape[0])
+
+        self.freqText.setText(str(self.fftXValues[indexInData][0]*xAxisScale))
+        self.isFreqValid = True
+
+
+
+    def closeEvent(self, event):
+        global __widget_id__
+        __widget_id__ = None
+        del self.par.widgets[self.id]
+
+        self.board_config.unobserve(self, 'lastDataSet')
+
+
+def addFrequencyExtractWidget():
+    global __widget_id__
+    if __widget_id__:
+        global_objects.get_global('area').widgets[__widget_id__].setFocus()
+    else:
+        nid = kcgw.idg.genid()
+        __widget_id__ = nid
+        w = FrequencyExtractWidget(nid, global_objects.get_global('area'))
+        global_objects.get_global('area').newWidget(w, "Frequency Extract", nid, widget_type=4)
+
+kcgw.register_widget(QtGui.QIcon(config.icon_path("sproject.svg")), "Frequency Extract", addFrequencyExtractWidget, "Ctrl+e")

+ 3 - 1
KCG/widgets/__init__.py

@@ -1 +1,3 @@
-__all__ = ['AcquireSettingsWidget', 'SingleReadWidget', 'TimingWidget', 'TimescanWidget', 'UpdateCalibrationWidget', 'EpicsWidget', 'CorrelationWidget']#, 'AdcWidget', 'TestingWidget']#, 'CudaWidget'] #, 'ExampleWidget']
+__all__ = ['AcquireSettingsWidget', 'SingleReadWidget', 'TimingWidget',
+        'TimescanWidget', 'UpdateCalibrationWidget', 'EpicsWidget',
+        'CorrelationWidget', 'FrequencyExtractWidget']#, 'AdcWidget', 'TestingWidget']#, 'CudaWidget'] #, 'ExampleWidget']