Browse Source

Introduce 50ohm background subtraction for timescan

also version in setup.py update
Patrick Schreiber 6 years ago
parent
commit
ffd09b6923
8 changed files with 100 additions and 24 deletions
  1. 11 6
      KCG/base/backendinterface.py
  2. 4 1
      KCG/base/kcg.py
  3. 4 1
      KCG/base/plotWidget.py
  4. 6 3
      KCG/base/settings.py
  5. 3 0
      KCG/config.cfg
  6. 1 1
      KCG/config.py
  7. 63 10
      KCG/widgets/timingWidget.py
  8. 8 2
      setup.py

+ 11 - 6
KCG/base/backendinterface.py

@@ -1145,12 +1145,13 @@ def _bif_start_time_scan(board_id, c_frm, c_to, f_frm, f_to, timescan_progressba
                         else:
                             buckets = data.array[self.bucket_to_use::config.bunches_per_turn, adc]
                         heatmap[adc, f_step, c_step] = float(buckets.sum()) / buckets.shape[0]
-                        if heatmap[adc, f_step, c_step] > maximum[adc, 0]:
-                            maximum[adc, 0] = heatmap[adc, f_step, c_step]
-                            maximum[adc, 1] = coarse
-                            maximum[adc, 2] = fine
-                        if minimum[adc] is None or minimum[adc] > heatmap[adc, f_step, c_step]:
-                            minimum[adc] = heatmap[adc, f_step, c_step]
+                        # Uncomment this to change back to the old (non functional) method of maxima determination
+                        # if heatmap[adc, f_step, c_step] > maximum[adc, 0]:
+                        #     maximum[adc, 0] = heatmap[adc, f_step, c_step]
+                        #     maximum[adc, 1] = coarse
+                        #     maximum[adc, 2] = fine
+                        # if minimum[adc] is None or minimum[adc] > heatmap[adc, f_step, c_step]:
+                        #     minimum[adc] = heatmap[adc, f_step, c_step]
 
                     self.pbarSignal.emit(((c_step * (f_to - f_frm + 1)) + f_step) + 1)
 
@@ -1187,6 +1188,10 @@ def _bif_start_time_scan(board_id, c_frm, c_to, f_frm, f_to, timescan_progressba
                 ]
         )
 
+#        maximum = []
+        for adc, a in enumerate(heatmap):
+            f, c = np.unravel_index(np.argmax(a), a.shape)
+	    maximum[adc] = [a[f, c], c+c_frm, f+f_frm]
 
         m = [np.min(heatmap[heatmap != 0]), np.max(heatmap)]  # this gives the same levels for all 4 adcs
         plot_func(heatmap, levels=m, ranges=[c_frm,c_to,f_frm,f_to], newTitle=str(tr("sw", "Coarserange:{c_f}-{c_t} ; Finerange:{f_f}-{f_t}")).format(

+ 4 - 1
KCG/base/kcg.py

@@ -109,6 +109,8 @@ def readconfig(parent):
         config.save_location = os.getcwd()
     else:
         config.save_location = config.default_save_location
+    
+    storage.storage.offset_correction = config.fifty_ohm_timescan_datafile
 
 
 _MultiView_Name_ = "MultiView"
@@ -456,7 +458,8 @@ class Gui(QtGui.QMainWindow):
                 QtGui.QMessageBox.information(self, "Change Language", "Language change takes effect after Gui restart", 1)
             if setting == 'advanced_control':
                 self.showAdvancedControl(getattr(self.storage, setting))
-
+#	    if setting == 'offset_correction':
+#		config.fifty_ohm_timescan_datafile = getattr(self.storage, setting)
             for bid in available_boards.board_ids:
                 try:
                     if bif.bk_get_config(bid, setting) != None:

+ 4 - 1
KCG/base/plotWidget.py

@@ -2,7 +2,10 @@
 This Module implements the Plot Windows used in KCG
 """
 import pyqtgraph as pg
-pg.setConfigOption('useOpenGl', True)
+try:  # on some versions of pyqtgraph useOpenGl is no valid option
+    pg.setConfigOption('useOpenGl', True)
+except:
+    pass
 pg.setConfigOption('background', 'w')
 pg.setConfigOption('foreground', 'k')
 import numpy as np

+ 6 - 3
KCG/base/settings.py

@@ -28,6 +28,7 @@ class Settings(kcgw.KCGWidgets):
         self.headerTick = self.build_new_setting(QtGui.QCheckBox(tr("Button", "Header")), 'header')
         self.subDirName = self.build_new_setting(self.createInput(self.storage_handler.subdirname, width=320), 'subdirname')
         self.dirName = self.build_new_setting(self.createInput(self.storage_handler.save_location, width=320), 'save_location')
+        self.timescan_offset_correction = self.build_new_setting(self.createInput(self.storage_handler.offset_correction, width=320), 'offset_correction')
         self.language = self.build_new_setting(QtGui.QComboBox(), 'language')
         self.advanced_control = self.build_new_setting(self.createCheckbox(tr("Label", "Enable Advanced Table View")), 'advanced_control')
         for lang in self.langlist:
@@ -62,9 +63,11 @@ class Settings(kcgw.KCGWidgets):
         self.grid.addWidget(self.subDirName, 1, 1)
         self.grid.addWidget(self.createLabel(tr("Label", "Save location:")), 2, 0)
         self.grid.addWidget(self.dirName, 2, 1)
-        self.grid.addWidget(self.createLabel(tr("Label", "Language")), 3, 0)
-        self.grid.addWidget(self.language, 3, 1)
-        self.grid.addWidget(self.advanced_control, 4, 0)
+        self.grid.addWidget(self.createLabel(tr("Label", "Timescan Offset Correction:")), 3, 0)
+        self.grid.addWidget(self.timescan_offset_correction, 3, 1)
+        self.grid.addWidget(self.createLabel(tr("Label", "Language")), 4, 0)
+        self.grid.addWidget(self.language, 4, 1)
+        self.grid.addWidget(self.advanced_control, 5, 0)
         self.hbox = QtGui.QHBoxLayout()
         self.layout.addLayout(self.hbox)
         self.hbox.addStretch(1)

+ 3 - 0
KCG/config.cfg

@@ -124,3 +124,6 @@ device_list = []
 device_names = {'test0': 'ich_bin_toll', 'test1': 'ne'}
 # num_dummy_boards is the number of dummy boards to create
 num_dummy_boards = 5
+
+# Datafile whith Timescandata for 50ohm termination
+fifty_ohm_timescan_datafile = "Put 'fifty_ohm_timescan_datafile = path_to_50_ohm_termination_timescanfile' into ~/.kcg/config.cfg"

+ 1 - 1
KCG/config.py

@@ -139,7 +139,7 @@ class Configuration(object):
         Misc_conf = ['newPlotLiveIcon', 'newPlotDataIcon', 'timingIcon', 'singleReadIcon',
                      'acquireSettingsIcon', 'startIcon', 'stopIcon', 'logIcon', 'logCommentIcon', 'guiIcon', 'style',
                      'board_detection_method', 'device_list', 'device_names',
-                     'num_dummy_boards']
+                     'num_dummy_boards', 'fifty_ohm_timescan_datafile']
 
         try:
             machine_c = ConfSection('Machine', Machine_conf, config, log_level=self._log_level)

+ 63 - 10
KCG/widgets/timingWidget.py

@@ -14,6 +14,7 @@ from ..base import backendinterface as bif
 from ..base.groupedelements import Elements
 from ..base.globals import glob as global_objects
 from .. import config
+from ..base import storage
 
 tr = kcgw.tr
 
@@ -68,12 +69,22 @@ class timingPlotWidget(kcgw.KCGWidgets):
         self.position_label = self.createLabel("")
         self.position_label.setAlignment(QtCore.Qt.AlignCenter)
         self.plot_type_switcher = self.createSwitch(connect=self.switch)
+        self.zero_correction_switcher = self.createSwitch(connect=self.zero_correction)
+        self.uses_zero_correction = False
+        self.zero_correction_values = None
 
         # ------[ Add Elements to various layouts ]--------------
         self.headerLayout.addWidget(self.position_label)
         self.headerLayout.addWidget(self.createLabel("Colour Plot"))
         self.headerLayout.addWidget(self.plot_type_switcher)
         self.headerLayout.addWidget(self.createLabel("Line Plot"))
+        t = QtGui.QFrame()
+        t.setFrameShape(QtGui.QFrame.VLine)
+        t.setFrameShadow(QtGui.QFrame.Sunken)
+        self.headerLayout.addWidget(t)
+        self.headerLayout.addWidget(self.createLabel("RawData"))
+        self.headerLayout.addWidget(self.zero_correction_switcher)
+        self.headerLayout.addWidget(self.createLabel("Corrected"))
         self.headerLayout.setAlignment(QtCore.Qt.AlignRight)
         self.layout.addWidget(self.adc1_plot_widget, 0, 0)
         self.layout.addWidget(self.adc2_plot_widget, 0, 1)
@@ -102,6 +113,46 @@ class timingPlotWidget(kcgw.KCGWidgets):
             self.colour_plot()
             self.plot()
 
+    def zero_correction(self):
+        """
+        Toggle Zero (50Ohm) Correction
+        """
+	# Note: when selecting a slice the upper bound has to be included since that's how the timescan works. Python array slicing does not include the upper bound => +1
+        if self.uses_zero_correction:
+            self.uses_zero_correction = False
+            self.data += self.zero_correction_values[:, self.xrange[0]:self.xrange[1]+1, self.yrange[0]:self.yrange[1]+1]
+
+        else:
+            self.uses_zero_correction = True
+            if self.zero_correction_values is None:
+                # Adjust for closed measurement of 0 (Measured using a 50 ohm impedance
+                # This will read the complete file into memory. Could be optimized to read only necessary values
+#                f = file(config.fifty_ohm_timescan_datafile)
+		f = file(storage.storage.offset_correction)
+                c_adc = -1  # -1 because first adc will have #ADC0 and this will increment c_adc
+                self.zero_correction_values = np.zeros((4, 32, 16))  # we know there are 4 adcs, 16 coarse delays and 32 fine delays
+		all_check = np.zeros((4, 32, 16), dtype=np.bool)
+                for line in f:
+                    line = line.strip()
+                    if line == "": continue  # skip empty lines
+                    if line.startswith("#"):
+                        c_adc += 1  # c_adc = int(line.split("_")[-1])
+                        continue
+                    coarse, fine, value = line.split(";")
+                    self.zero_correction_values[c_adc, int(fine), int(coarse)] = value
+		    all_check[c_adc, int(fine), int(coarse)] = True
+		if False in all_check:
+		    logging.warn("Read 50Ohm timescan for offset correction does not include all delay values")
+
+            self.data -= self.zero_correction_values[:, self.xrange[0]:self.xrange[1]+1, self.yrange[0]:self.yrange[1]+1]
+
+	maxima = np.zeros((4, 3))
+	for adc, a in enumerate(self.data):
+	    f, c = np.unravel_index(np.argmax(a), a.shape)
+	    maxima[adc] = [a[f, c], c+self.yrange[0], f+self.xrange[0]]
+
+        self.plot(maxima=maxima)
+
     def colour_plot(self):
         """
         Initialize Color Plot
@@ -200,7 +251,9 @@ class timingPlotWidget(kcgw.KCGWidgets):
         :param spacing:
         :return:
         """
-        return [str(int(v)) for v in values]
+	if np.mean(values) > 3:
+	    return [str(int(v)) for v in values]
+        return [str(v) for v in values]
 
     def line_plot(self):
         """
@@ -298,15 +351,15 @@ class timingPlotWidget(kcgw.KCGWidgets):
                 self.setWindowTitle(tr("Heading", "Timescan Result:") + " " + newTitle + " " +
                                     available_boards.get_board_name_from_id(self.board_id))
 
-            if maxima is not None:
-                self.adc1_plot_widget.getPlotItem().setTitle(str(tr("Heading", "ADC 1: Maximum C:{c} F:{f}")).format(
-                    c=int(maxima[0, 1]), f=int(maxima[0, 2])))
-                self.adc2_plot_widget.getPlotItem().setTitle(str(tr("Heading", "ADC 2: Maximum C:{c} F:{f}")).format(
-                    c=int(maxima[1, 1]), f=int(maxima[1, 2])))
-                self.adc3_plot_widget.getPlotItem().setTitle(str(tr("Heading", "ADC 3: Maximum C:{c} F:{f}")).format(
-                    c=int(maxima[2, 1]), f=int(maxima[2, 2])))
-                self.adc4_plot_widget.getPlotItem().setTitle(str(tr("Heading", "ADC 4: Maximum C:{c} F:{f}")).format(
-                    c=int(maxima[3, 1]), f=int(maxima[3, 2])))
+        if maxima is not None:
+            self.adc1_plot_widget.getPlotItem().setTitle(str(tr("Heading", "ADC 1: Maximum C:{c} F:{f}")).format(
+	        c=int(maxima[0, 1]), f=int(maxima[0, 2])))
+	    self.adc2_plot_widget.getPlotItem().setTitle(str(tr("Heading", "ADC 2: Maximum C:{c} F:{f}")).format(
+	        c=int(maxima[1, 1]), f=int(maxima[1, 2])))
+	    self.adc3_plot_widget.getPlotItem().setTitle(str(tr("Heading", "ADC 3: Maximum C:{c} F:{f}")).format(
+	        c=int(maxima[2, 1]), f=int(maxima[2, 2])))
+	    self.adc4_plot_widget.getPlotItem().setTitle(str(tr("Heading", "ADC 4: Maximum C:{c} F:{f}")).format(
+	        c=int(maxima[3, 1]), f=int(maxima[3, 2])))
         if self.plot_type == 'line':
             # self.line_plot()
             def reshape(data):

+ 8 - 2
setup.py

@@ -1,11 +1,17 @@
 #!/usr/bin/python
 from setuptools import setup, find_packages
-
+import time, subprocess
 DESCRIPTION = "KCG KAPTURE Control Gui"
+git_count = subprocess.check_output(["git", "rev-list", "--count", "HEAD"]).strip()
+version_time = time.strftime("%d%m%y")
+VERSION = "0.3.2."+git_count+"."+version_time+"-beta"
+with open("KCG/VERSION", 'w') as vfile:
+    vfile.write(VERSION)
 
 setup(
     name='KCG',
-    version='0.3.2.197.0704-beta',
+#    version='0.3.2.197.0704-beta',
+    version=VERSION,
     author='Patrick Schreiber',
     author_email='uldfk@student.kit.edu',
 #    license='GPL',