Browse Source

Remove dead-time between pulses in Reconstruction

Timo Dritschler 3 years ago
parent
commit
3500a1afab
2 changed files with 90 additions and 64 deletions
  1. 58 27
      KCG/base/backend/DataSet.py
  2. 32 37
      KCG/widgets/PlotWidget.py

+ 58 - 27
KCG/base/backend/DataSet.py

@@ -19,7 +19,7 @@ except:
     from constants import KARA
 
 
-#FIXME: This is devide dependent and needs to be in the config file!!H[
+#FIXME: This is device dependent and needs to be in the config file!!
 HEADER_SIZE_BYTES = 32
 
 
@@ -109,6 +109,7 @@ class DataSet(object):
                 self.c25b = delays['c25b']
                 self.f = delays['f']
             except:
+
                 pass
 
         if decodedData is not None:
@@ -163,7 +164,7 @@ class DataSet(object):
         #FIXME: THIS IS A TRIAGE!
         # This is a bandaid patch to make peak reconstruction at least *somewhat*
         # working again. We will only use the finedelays from current
-        # configuration. This will inevitably be incorrect, of data is stored to
+        # configuration. This will inevitably be incorrect, if data is stored to
         # harddrive and then opened again in a new session with different settings
         # and configuration. Or on a different KAPTURE system alltogether. So we
         # will eventually need to think about a way to couple calibration,
@@ -193,10 +194,26 @@ class DataSet(object):
         time_between_bunches_ps = time_between_bunches_s * (1000**4)
 
 
-
-        finedelays = board_config.get("chip_delay")
         finedelay_factor = board_config.get("chip_delay_factor")
-        finedelays = [i*finedelay_factor for i in finedelays]
+        finedelays = board_config.get("chip_delay")
+        finedelays = [i * finedelay_factor for i in finedelays]
+
+
+
+        #FIXME:
+        #NOTE:
+        # Michele Caselle requested, that the 'dead space' between each
+        # individual bunch be removed. This means, we do not calculate the actual
+        # time in ps between each bunch, based on the machine geometry and
+        # configuration, but just assume that the next bunch starts exactly 3ps
+        # (the smallest possible fine-delay) after the last bunch has ended. 
+        # Therefore, we just assume that the time between bunches is at max the
+        # highest fine-delay we con configure + 3
+
+        time_between_bunches_ps = 3
+        finedelay_max = board_config.get("chip_delay_max")
+        time_between_bunches_ps += finedelay_max * finedelay_factor
+
 
 
         #FIXME: We need a better way to understand how the ADCs are distributed
@@ -214,10 +231,22 @@ class DataSet(object):
         adcdelays_ps[:4] = [i + fmc1_delay for i in finedelays[:4]]
         adcdelays_ps[4:] = [i + fmc2_delay for i in finedelays[4:]]
 
+        #NOTE:
+        # The Track-and-Hold (TH) timings do not have an impact on the actual
+        # distribution of data across the time domain! The THs only "latches" an
+        # analogue value at a certain point in time and holds it, so the ADCs
+        # have time to convert the analogue value into a digital one. 
+        adcdelays_ps = finedelays
+
 
-        #Express the delays as fractions of full bunches
+        #Express the delays as fractions of full timing distance between bunches
         adcdelays_ps = [i / time_between_bunches_ps for i in adcdelays_ps]
 
+        print("###############################")
+        print(adcdelays_ps)
+        print("###############################")
+
+
         return adcdelays_ps
 
 
@@ -403,7 +432,7 @@ class DataSet(object):
         array = array[:, np.array(selector)]
 
         #At this point, 'array' is basically just a truncated version of the
-        #raw-date in 'self.array' without the bunch-numbers
+        #raw-data in 'self.array' without the bunch-numbers
 
 
         if isinstance(adc, list):
@@ -417,45 +446,44 @@ class DataSet(object):
                 #8 ADCs in the future?
                 finedelays = np.repeat(finedelays, 2)
 
-
         if calibrate:
             for i in range(self.adcNumber):
                 finedelays[i] = (theCalibration.calibrateX(i, self.c330, self.c25, finedelays[i], self.c25b, self.calibId) -  theCalibration.calibrateX(0, self.c330, self.c25, 0, self.c25b, self.calibId) )*1e12
+
         else:
-            finedelays = finedelays*3
+            #FIXME:
+            #WHAT DOES THIS RANDOM x3 DO!?
+            #finedelays = finedelays*3
+            pass
 
 
 
         #FIXME: Why? What purpose does this serve?
         #Why do we divide by 100!?
-        if self.datax is not None:
-            finedelays = self.datax - np.min(self.datax)
-        finedelays = finedelays/100.0
 
+        #Disabled for now, until we understand why this was even implemented
+        # if self.datax is not None:
+        #     finedelays = self.datax - np.min(self.datax)
+        #finedelays = finedelays/100.0
 
 
         if not turnbyturn:
-            #FIXME: How about we nest ALL the calls! Genious!! (NOT!!)
-            a = np.array(
-                    np.reshape(
-                        np.repeat(
-                            np.arange(0, len(array)), len(selector)), -1), dtype=np.float)
-
-            #'array' should have numBunches many entries. So 't' should now be
+            #'array' should have numBunches many entries. So 'a' should now be
             # [0,1,2,3,4 ... NumBunches]
-            t = np.arange(0, len(array))
+            a = np.arange(0, len(array))
 
-            #Now 't' should be numADC*numBunches long and internally repeat the
+            #Now 'a' should be numADC*numBunches long and internally repeat the
             #same each element of the previous array len(selector)-times in a row
             #Think [0,0,0,0,  1,1,1,1,  2,2,2,2 ... len(array)], if len(selector)
             #would be 4
-            t = np.repeat(t, len(selector))
+            a = np.repeat(a, len(selector))
 
-            #But ... t already IS 1-dimensional? Whay reshape it with -1 AGAIN?
-            t = np.reshape(t, -1)
+            #But ... a already IS 1-dimensional? Whay reshape it with -1 AGAIN?
+            #a = np.reshape(a, -1)
+
+            #And finally, we turn a into a np.float type array...
+            a = np.array(a, dtype=np.float)
 
-            #And finally, we turn t into a np.float type array...
-            t = np.array(t, dtype=np.float)
 
 
         else:
@@ -468,6 +496,7 @@ class DataSet(object):
 
         # 'a' is a list of all the bunch-bumbers (basically X-Coordinates) which
         # the individual datapoints from the ADCs belong to.
+
         # 'b' is a list of all fine-delays for all the ADCs, repeated for numBunches times.
         # This means 'a+b' is X-Coordinates with respect to the individual
         # delays of the ADCs. The "calibrated" X-Coordinates, so to say
@@ -479,7 +508,7 @@ class DataSet(object):
         array = array.flatten()
 
         # Okay, so if I understand this correctly, 'array' should now be
-        # basically just one long string of values with all the the ADCs in
+        # basically just one long vector of values with all the the ADCs in
         # sequence.
         # Basically:
         # [ADC 1 Bunch1, ADC 1 Bunch2, ADC 1 Bunch3 ... ADC 1 Bunch n,
@@ -504,6 +533,8 @@ class DataSet(object):
             return ret
 
 
+        #FIXME: I assume the check for ==6 is because of the 'Working channels'
+        # thing that used to be in a previous version?
         if len(selector) == 6:
             if adc > 4:
                 adc -= 2

+ 32 - 37
KCG/widgets/PlotWidget.py

@@ -406,7 +406,7 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
 
 
 
-    def plotPeak(self, data):
+    def plotPeak(self, data)
         """
         Plot the datapoints of all available ADCs as time-series data and
         optionally do a polyfit between the points to visualize an
@@ -419,14 +419,14 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
         self.img.clear()
         self.plotItemPlotScatter.show()
         self.plotItemPlotScatter1.show()
-
+        
         baseline = []
-        #doFit = 6 if self.fittGauss.isChecked() else 0
+        doFit = 6 if self.fittGauss.isChecked() else 0
 
         #Currently not supported / cleanup required
         #if doFit > 0:
         if False:
-
+             
             x = np.reshape(data[0][0], (-1, doFit))
             y = np.reshape(data[0][1], (-1, doFit))
 
@@ -435,21 +435,21 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
             positive = np.abs(valmax) > np.abs(valmin)
             #print('positive', positive)
 
-
+            
             tmp = y.T
             for line in tmp:
                 if positive:
                     baseline.append(np.mean(line[np.where(line < 15)]))
                 else:
                     baseline.append(np.mean(line[np.where(line > -15)]))
-
+            
             #print(baseline)
             y = y-baseline
-
+            
             def gauss(x, sigma, mu, A):
                 return A*np.exp(-0.5*((x-mu)/sigma)**2)
 
-            fitx = np.linspace(np.min(x[0])*0.5, np.max(x[0])*1.5, 25)
+            fitx = np.linspace(np.min(x[0])*0.5, np.max(x[0])*1.5, 25)   
             for i, line in enumerate(x):
                 if len(self.plotItemFit) < i+1:
                     item = pg.PlotDataItem(pen=pg.mkPen(QColor(192, 57, 43), width=0.5), autoDownsample=True, clipToView=True )
@@ -467,19 +467,14 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
                     traceback.print_exc()
                     pass
 
-        #Deactivatedf for now
-        #if doFit:
-        if False:
+        if doFit:
             self.plotItemPlotScatter.setData(np.reshape(x,-1), np.reshape(y,-1))
-        else:
+        else:    
             self.plotItemPlotScatter.setData(data[0].transpose())
             self.plotItemPlotScatter1.setData(data[1].transpose())
-            #ScatterPlots just want a tuple of two arrays, and combines them
-            #together to form X,Y coordinate pairs.
-
-
-        #self._enableCustomAutoRange(data[0][1])
-        self.plotItem.setClipToView(True)
+        
+        self._enableCustomAutoRange(data[0][1])
+        self.plotItem.setClipToView(False)
 
 
 
@@ -523,13 +518,13 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
         #self.plotItemPlotScatter2.clear()
         #self.plotItem.resetTransform()
         #self.plotItem.getAxis('bottom').setScale()
-
+        
 
         self.img.clear()
         self.img2.clear()
         self.img.hide()
         self.img2.hide()
-
+        
         self.gradient_legend.hide()
         try:
             self.removeItem(self.gradient_legend)
@@ -537,7 +532,7 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
         except Exception as e:
             if not "Could not determine index of item" in str(e):
                 raise
-
+ 
 
         if self._type_changed:
             #self.plotItem.autoBtnClicked()
@@ -597,7 +592,7 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
                 if len(data) < 9:
                     data= data[0]
                 data = np.abs(data).transpose()
-
+                
                 self.addItem(self.gradient_legend)
 
                 self.gradient_legend.show()
@@ -623,7 +618,7 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
                 self.plotItem.setClipToView(True)
 
         if self.plotType == PlotType.Heatmap:
-
+           
             self.addItem(self.gradient_legend)
 
             self.gradient_legend.show()
@@ -687,7 +682,7 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
             self.plotItem.setClipToView(True)
 
         if self.plotType == PlotType.Trains:
-
+            
             if len(data) < 9:
                 maxv = 0
                 minv = 4000
@@ -712,12 +707,12 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
                 self.plotItemPlot[0].setData(data)
 
                 self._enableCustomAutoRange(data)
-
+        
         if self.plotType in [PlotType.Combined]:
             self.img.clear()
             self.plotItemPlotScatter.show()
             self.plotItemPlotScatter1.show()
-
+            
             self.plotItemPlotScatter.setData(data[0].transpose())
             self.plotItemPlotScatter1.setData(data[1].transpose())
 
@@ -739,7 +734,7 @@ class SubPlotWidget(pg.GraphicsLayoutWidget):
                 self.error_label.show()
             else:
                 self.no_data_label.show()
-
+            
 
         if autorange:
             self.plotItem.getViewBox().autoRange()
@@ -893,7 +888,7 @@ class PlotWidget(kcgw.KCGWidgets):
             self.adcCheckBox.append(self.createCheckbox(text="ADC "+str(i+1), connect=self.change_adc, color=colours[i]))
             self.adc_checkbox_layout.addWidget(self.adcCheckBox[i])
             self.group.addButton(self.adcCheckBox[i], i+1)
-
+        
         self.adcCheckBox[0].setChecked(True)
         self.groupWidget = QtGui.QWidget()
         self.groupWidget.setLayout(self.adc_checkbox_layout)
@@ -943,20 +938,20 @@ class PlotWidget(kcgw.KCGWidgets):
 
         self.groupWidgetCompare.hide()
 
-
+        
         self.fft_mode = QtGui.QComboBox(self)
         self.fft_mode.addItem("Image") #0
         self.fft_mode.addItem("All") #1
         self.fft_mode.addItem("Mean") #1
         for i in range(184):
-            self.fft_mode.addItem("Bucket {}".format(i))
+            self.fft_mode.addItem("Bucket {}".format(i)) 
         self.fft_mode.currentIndexChanged.connect(lambda: [self.change_adc(), self.changePlotType(self.theType)])
         self.fft_log = self.createCheckbox(text="Log", connect=lambda: self.change_adc())
 
         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.addWidget(self.fft_mode)
         self.from_to_layout.addWidget(self.fft_log)
         self.from_to_layout.addStretch()
@@ -998,7 +993,7 @@ class PlotWidget(kcgw.KCGWidgets):
                 self.adcCheckBox[0].setChecked(True)
         else:
             self.adc = self.group.checkedId()-1
-
+        
         self.change_identifier_text()
         self.plot(self.theType)
 
@@ -1059,8 +1054,8 @@ class PlotWidget(kcgw.KCGWidgets):
                 style += self.defaultButtonStyleSheet
             style += "QPushButton:focus{background-color: lightgrey!important; border-color: lightblue;}"  # Note: this does not work
             button.setStyleSheet(style)
-
-
+        
+        
         if self.theType == PlotType.Trains:
             self.group.setExclusive(False)
         else:
@@ -1075,12 +1070,12 @@ class PlotWidget(kcgw.KCGWidgets):
         else:
             self.makeMean.hide()
             self.fittGauss.hide()
-
+        
         if self.theType == PlotType.FFT:
             self.fft_mode.show()
             self.fft_log.show()
             if self.fft_mode.currentIndex() > 0:
-               self.group.setExclusive(False)
+               self.group.setExclusive(False) 
             else:
                 self.group.setExclusive(True)
         else:
@@ -1102,7 +1097,7 @@ class PlotWidget(kcgw.KCGWidgets):
             self.do_plot(type)
         except Exception as e:
             print('plot wrapper except')
-
+            
             traceback.print_exc()
             if self.data is None or len(self.data.array) == 0:
                 self.changePlotType(NO_DATA)