|
@@ -14,7 +14,6 @@ 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
|
|
|
|
|
@@ -22,8 +21,6 @@ __widget_id__ = None
|
|
|
__timing_plot_widget_id__ = {}
|
|
|
__timing_plot_widget__ = None
|
|
|
|
|
|
-BUNCHES_PER_TURN = config.bunches_per_turn
|
|
|
-
|
|
|
class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
"""
|
|
|
The Timescan result plot subwindow.
|
|
@@ -43,8 +40,6 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
|
|
|
# ------[ Variable declaration ]------------
|
|
|
self.plot_type = "colour" # The Plot Type for this window (Changeable in this window)
|
|
|
- self.xrange = (None, None)
|
|
|
- self.yrange = (None, None)
|
|
|
self.x = None # Number of Ticks in the x-direction This is set by the gui programmatically
|
|
|
self.y = None # Number of Ticks in the y-direction This is set by the gui programmatically
|
|
|
self.data = None # Data to plot
|
|
@@ -69,22 +64,12 @@ 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)
|
|
@@ -113,46 +98,6 @@ 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
|
|
@@ -169,33 +114,27 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
self.adc3.mouseClickEvent = lambda x: self.click("ADC 3", x)
|
|
|
self.adc4.mouseClickEvent = lambda x: self.click("ADC 4", x)
|
|
|
|
|
|
- def xtickStrings(values, scale, spacing):
|
|
|
- """
|
|
|
- Generate the strings for ticks
|
|
|
- """
|
|
|
- return [str(i + self.xrange[0]) for i in range(int(values[0]), int(values[-1]),int(spacing))]
|
|
|
-
|
|
|
- def ytickStrings(values, scale, spacing):
|
|
|
+ def tickStrings(values, scale, spacing):
|
|
|
"""
|
|
|
Generate the strings for ticks
|
|
|
"""
|
|
|
- return [str(int(i) + self.yrange[0]) for i in values]
|
|
|
+ if len(values) > 20:
|
|
|
+ return [str(i) for i in range(int(values[0]), int(values[-1]), 2)]
|
|
|
+ else:
|
|
|
+ return [str(int(i)) for i in values]
|
|
|
|
|
|
# ----------[ Configure and add color plots for ADC1 ]----------
|
|
|
|
|
|
for i in range(1, 5):
|
|
|
- getattr(self, "adc{}_plot_widget".format(i)).enableAutoRange() #axis=getattr(self, "adc{}_plot_widget".format(i)).getViewBox().YAxis)
|
|
|
getattr(self, "adc{}_plot_widget".format(i)).getPlotItem().setLabel("left", tr("Heading", "Coarse delay"))
|
|
|
getattr(self, "adc{}_plot_widget".format(i)).getPlotItem().setLabel("bottom", tr("Heading", "Fine delay"))
|
|
|
getattr(self, "adc{}_plot_widget".format(i)).plotItem.addItem(getattr(self, "adc"+str(i)))
|
|
|
bax = getattr(self, "adc{}_plot_widget".format(i)).plotItem.getAxis('bottom')
|
|
|
lax = getattr(self, "adc{}_plot_widget".format(i)).plotItem.getAxis('left')
|
|
|
-
|
|
|
- bax.tickSpacing = self.spacing
|
|
|
- bax.tickStrings = xtickStrings
|
|
|
+ bax.setTickSpacing(levels=[(1, 2.5),])
|
|
|
+ bax.tickStrings = tickStrings
|
|
|
lax.setTickSpacing(levels=[(1, 1.5),])
|
|
|
- lax.tickStrings = ytickStrings
|
|
|
-
|
|
|
+ lax.tickStrings = tickStrings
|
|
|
|
|
|
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]])
|
|
@@ -225,8 +164,8 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
:param spacing: See pyqtgraph.AxisItem.tickStrings
|
|
|
:return: See pyqtgraph.AxisItem.tickStrings
|
|
|
"""
|
|
|
- coarses = [self.yrange[0] + i//(self.x) for i in values]
|
|
|
- fines = [self.xrange[0] + i%(self.x) for i in values]
|
|
|
+ coarses = [i//(self.x) for i in values]
|
|
|
+ fines = [i%(self.x) for i in values]
|
|
|
return [str(int(c))+"\n"+str(int(f)) for c, f in zip(coarses, fines)]
|
|
|
|
|
|
def spacing(self, minVal, maxVal, size):
|
|
@@ -238,10 +177,10 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
:param size: See pyqtgraph.AxisItem.tickSpacing
|
|
|
:return: See pyqtgraph.AxisItem.tickSpacing
|
|
|
"""
|
|
|
- if maxVal - minVal < 10.:
|
|
|
+ if maxVal - minVal < 20.:
|
|
|
return [(1, 0),]
|
|
|
else:
|
|
|
- return [(round((maxVal-minVal)/10.), 0),]
|
|
|
+ return [(round((maxVal-minVal)/20.), 0),]
|
|
|
|
|
|
def y_axis_strings(self, values, scale, spacing):
|
|
|
"""
|
|
@@ -251,9 +190,7 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
:param spacing:
|
|
|
:return:
|
|
|
"""
|
|
|
- if np.mean(values) > 3:
|
|
|
- return [str(int(v)) for v in values]
|
|
|
- return [str(v) for v in values]
|
|
|
+ return [str(int(v)) for v in values]
|
|
|
|
|
|
def line_plot(self):
|
|
|
"""
|
|
@@ -263,13 +200,10 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
self.plot_type = "line"
|
|
|
|
|
|
for i in range(1, 5):
|
|
|
- getattr(self, "adc{}_plot_widget".format(i)).enableAutoRange() #axis=getattr(self, "adc{}_plot_widget".format(i)).getViewBox().YAxis)
|
|
|
getattr(self, "adc{}_plot_widget".format(i)).getPlotItem().setLabel("left", tr("Heading", "Intensity"))
|
|
|
getattr(self, "adc{}_plot_widget".format(i)).getPlotItem().setLabel("bottom", tr("Heading", "Coarse over Fine"))
|
|
|
bax = getattr(self, "adc{}_plot_widget".format(i)).plotItem.getAxis('bottom')
|
|
|
lax = getattr(self, "adc{}_plot_widget".format(i)).plotItem.getAxis('left')
|
|
|
-
|
|
|
- bax.setTickSpacing()
|
|
|
bax.tickSpacing = self.spacing
|
|
|
bax.tickStrings = self.line_plot_axis_strings
|
|
|
lax.setTickSpacing()
|
|
@@ -298,26 +232,25 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
"""
|
|
|
event.accept()
|
|
|
pos = event.pos()
|
|
|
- self.position_label.setText(adc + " - " + str(int(pos.x())+self.xrange[0]) + ":"+str(int(pos.y())+self.yrange[0]))
|
|
|
+ self.position_label.setText(adc + " - " + str(int(pos.x())) + ":"+str(int(pos.y())))
|
|
|
if not self.inputsSet:
|
|
|
return
|
|
|
|
|
|
- self.c_input.setValue(int(pos.y())+self.yrange[0])
|
|
|
+ self.c_input.setValue(int(pos.y()))
|
|
|
if adc == "ADC 1":
|
|
|
- self.adc1_f_input.setValue(int(pos.x())+self.xrange[0])
|
|
|
+ self.adc1_f_input.setValue(int(pos.x()))
|
|
|
elif adc == "ADC 2":
|
|
|
- self.adc2_f_input.setValue(int(pos.x())+self.xrange[0])
|
|
|
+ self.adc2_f_input.setValue(int(pos.x()))
|
|
|
elif adc == "ADC 3":
|
|
|
- self.adc3_f_input.setValue(int(pos.x())+self.xrange[0])
|
|
|
+ self.adc3_f_input.setValue(int(pos.x()))
|
|
|
elif adc == "ADC 4":
|
|
|
- self.adc4_f_input.setValue(int(pos.x())+self.xrange[0])
|
|
|
+ self.adc4_f_input.setValue(int(pos.x()))
|
|
|
|
|
|
- def plot(self, data=None, levels=None, ranges=None, newTitle=None, maxima=None):
|
|
|
+ def plot(self, data=None, levels=None, newTitle=None, maxima=None):
|
|
|
"""
|
|
|
Plot Data
|
|
|
:param data: (numpy 4d array) data to plot
|
|
|
:param levels: (tuple) Min and Max Values for color plot
|
|
|
- :param ranges: (list) From to range of coarse (y) and fine (x) delay scan
|
|
|
:param newTitle: (str) The title for the window
|
|
|
:param maxima: (list) Maximum for each adc
|
|
|
:return: -
|
|
@@ -330,10 +263,6 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
self.data = data # if called with no data a replot is performed (if data is set previously)
|
|
|
if levels is not None:
|
|
|
self.levels = levels
|
|
|
- if ranges is not None:
|
|
|
- self.yrange = ranges[0:2]
|
|
|
- self.xrange = ranges[2:4]
|
|
|
-
|
|
|
self.x = self.data.shape[1]
|
|
|
self.y = self.data.shape[2]
|
|
|
if self.plot_type == 'colour':
|
|
@@ -351,15 +280,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):
|
|
@@ -369,7 +298,6 @@ class timingPlotWidget(kcgw.KCGWidgets):
|
|
|
self.adc2_plot_widget.plotItem.clear()
|
|
|
self.adc3_plot_widget.plotItem.clear()
|
|
|
self.adc4_plot_widget.plotItem.clear()
|
|
|
-
|
|
|
self.adc1_plot_widget.plotItem.plot(reshape(self.data[0]))
|
|
|
self.adc2_plot_widget.plotItem.plot(reshape(self.data[1]))
|
|
|
self.adc3_plot_widget.plotItem.plot(reshape(self.data[2]))
|
|
@@ -423,18 +351,6 @@ class timingPart(kcgw.KCGWidgets):
|
|
|
self.fine_scan_min_spinbox = self.createSpinbox(0, bif.bk_get_config(board_id, 'chip_delay_max'), start_value=0)
|
|
|
self.fine_scan_max_spinbox = self.createSpinbox(0, bif.bk_get_config(board_id, 'chip_delay_max'), start_value=bif.bk_get_config(board_id, 'chip_delay_max'))
|
|
|
|
|
|
- self.average_one_bunch_label = self.createLabel(tr("Label", "Average bunch number"))
|
|
|
- self.average_all_bunches_checkbox = self.createCheckbox(tr("Button", "Average all bunches"), tr("Tooltip", "Average over signal from all bunches for timescan"),
|
|
|
- checked=True,connect=self.showAverageOneBunch)
|
|
|
- self.average_one_bunch_spinbox = self.createSpinbox(0, BUNCHES_PER_TURN-1, start_value=0)
|
|
|
- self.average_one_bunch_spinbox.setEnabled(False)
|
|
|
-
|
|
|
- self.average_threshold_label = self.createLabel(tr("Label", "Averaging Threshold"))
|
|
|
- self.average_threshold_checkbox = self.createCheckbox(tr("Button", "Use Threshold"), tr("Tooltip", "Average over signal from all bunches that are above/below the specified threshold for timescan"),
|
|
|
- checked=False,connect=self.considerThreshold)
|
|
|
- self.average_threshold_spinbox = self.createSpinbox(0, 2048, start_value=0)
|
|
|
- self.average_threshold_spinbox.setEnabled(False)
|
|
|
-
|
|
|
self.orbits_observe_spinbox = self.createSpinbox(1, 10000000, start_value=100)
|
|
|
self.orbits_skip_spinbox = self.createSpinbox(0, 100, start_value=2)
|
|
|
|
|
@@ -461,13 +377,7 @@ class timingPart(kcgw.KCGWidgets):
|
|
|
self.timeScanLayout.addWidget(self.orbits_observe_spinbox, 3, 2)
|
|
|
self.timeScanLayout.addWidget(self.createLabel("Orbits to Skip"), 4, 1)
|
|
|
self.timeScanLayout.addWidget(self.orbits_skip_spinbox, 4, 2)
|
|
|
- self.timeScanLayout.addWidget(self.average_all_bunches_checkbox, 5, 0)
|
|
|
- self.timeScanLayout.addWidget(self.average_one_bunch_label, 5, 1)
|
|
|
- self.timeScanLayout.addWidget(self.average_one_bunch_spinbox, 5, 2)
|
|
|
- self.timeScanLayout.addWidget(self.average_threshold_checkbox, 6, 0)
|
|
|
- self.timeScanLayout.addWidget(self.average_threshold_label, 6, 1)
|
|
|
- self.timeScanLayout.addWidget(self.average_threshold_spinbox, 6, 2)
|
|
|
- self.timeScanLayout.addWidget(self.time_scan_button, 7, 2)
|
|
|
+ self.timeScanLayout.addWidget(self.time_scan_button, 5, 2)
|
|
|
self.setTabOrder(self.fine_scan_max_spinbox, self.time_scan_button)
|
|
|
|
|
|
# --------[ End Time Scan Part ]-------------
|
|
@@ -633,24 +543,6 @@ class timingPart(kcgw.KCGWidgets):
|
|
|
if not self.adc1CoarseInput.isEnabled():
|
|
|
board.get_board_config(self.board_id).update('adc_1_delay_individual', -1) # Be careful this does no silent update
|
|
|
|
|
|
- def showAverageOneBunch(self):
|
|
|
- """
|
|
|
- Toggle to use an individual bunch for the averaging in the time delay scan or to use all bunches
|
|
|
- :return: -
|
|
|
- """
|
|
|
- self.average_one_bunch_spinbox.setEnabled(not self.average_all_bunches_checkbox.checkState())
|
|
|
- self.average_threshold_spinbox.setEnabled(self.average_all_bunches_checkbox.checkState() and self.average_threshold_checkbox.checkState())
|
|
|
- self.average_threshold_checkbox.setEnabled(self.average_all_bunches_checkbox.checkState())
|
|
|
- self.average_threshold_checkbox.setChecked(False)
|
|
|
-
|
|
|
- def considerThreshold(self):
|
|
|
- """
|
|
|
- Toggle to consider the Threshold for the averaging in the time delay scan
|
|
|
- :return: -
|
|
|
- """
|
|
|
- self.average_threshold_spinbox.setEnabled(self.average_threshold_checkbox.checkState() and self.average_all_bunches_checkbox.checkState())
|
|
|
-
|
|
|
-
|
|
|
def showTimeScan(self):
|
|
|
"""
|
|
|
Show the time scan part of this window
|
|
@@ -694,9 +586,7 @@ class timingPart(kcgw.KCGWidgets):
|
|
|
self.time_scan_progressbar,
|
|
|
self.plotWidget.plot,
|
|
|
orbits_observe = self.orbits_observe_spinbox.value(),
|
|
|
- orbits_skip = self.orbits_skip_spinbox.value(),
|
|
|
- bucket_to_use = self.average_one_bunch_spinbox.value() if self.average_one_bunch_spinbox.isEnabled() else None,
|
|
|
- threshold_counts = self.average_threshold_spinbox.value() if self.average_threshold_spinbox.isEnabled() else None
|
|
|
+ orbits_skip = self.orbits_skip_spinbox.value()
|
|
|
)
|
|
|
|
|
|
def setValueSilent(self, element, value):
|