TimingWidget.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. """
  2. This Module Is the Timingsettings subWindow.
  3. """
  4. import logging
  5. from PyQt4 import QtGui, QtCore
  6. import pyqtgraph as pg
  7. import numpy as np
  8. import h5py
  9. from ..base import kcgwidget as kcgw
  10. from ..base.backend import board
  11. from ..base.backend.board import available_boards
  12. from ..base import backendinterface as bif
  13. from ..base.groupedelements import Elements
  14. from ..base.globals import glob as global_objects
  15. from .. import config
  16. from ..base import storage
  17. from ..base.backend.CalibrationHandle import theCalibration
  18. tr = kcgw.tr
  19. import os
  20. __widget_id__ = None
  21. __timing_plot_widget_id__ = {}
  22. __timing_plot_widget__ = None
  23. BUNCHES_PER_TURN = config.bunches_per_turn
  24. # 88888888888d8b d8b 8888888b. 888
  25. # 888 Y8P Y8P 888 Y88b 888
  26. # 888 888 888 888
  27. # 888 88888888b.d88b. 88888888b. .d88b. 888 d88P 8888b. 888d888888888
  28. # 888 888888 "888 "88b888888 "88bd88P"88b8888888P" "88b888P" 888
  29. # 888 888888 888 888888888 888888 888888 .d888888888 888
  30. # 888 888888 888 888888888 888Y88b 888888 888 888888 Y88b.
  31. # 888 888888 888 888888888 888 "Y88888888 "Y888888888 "Y888
  32. # 888
  33. # Y8b d88P
  34. # "Y88P"
  35. class TimingPart(kcgw.KCGWidgets):
  36. """
  37. The actual timing settings window
  38. """
  39. def __init__(self, board_id, parent=None):
  40. """
  41. Initialise the timing settings window
  42. :param unique_id:
  43. :param parent:
  44. :return:
  45. """
  46. super(TimingPart, self).__init__()
  47. if __timing_plot_widget__:
  48. self.plotWidget = __timing_plot_widget__
  49. self.parent = parent
  50. self.board_id = board_id
  51. self.board_config = board.get_board_config(board_id)
  52. self.layout = QtGui.QGridLayout()
  53. self.outerLayout = QtGui.QVBoxLayout()
  54. self.outerLayout.addLayout(self.layout)
  55. self.setLayout(self.outerLayout)
  56. self.show_advanced = True
  57. # --------[ Create Labels and corresponding Fields ]---------
  58. def update_delay(which, spinbox):
  59. '''update the delays on the board'''
  60. val = getattr(self, spinbox).value()
  61. self.board_config.update(which, val)
  62. #if not self.show_advanced and "th" in which:
  63. # key = which[:-2] + "adc"
  64. # self.board_config.update(key, val)
  65. self.adc_number = self.board_config.get('adc_number')
  66. #board.get_board_config(board_id).set_delay(self.coarseInput.value())
  67. self.thdelayLabel = self.createLabel(tr("Label", "Total Delay"))
  68. #self.adc1thdelayLabel = self.createLabel(tr("Label", "2. ADC1 T/H Delay"))
  69. self.labelCoarseAdcDelay = self.createLabel("ADC")
  70. self.labelCoarseFpgaDelay = self.createLabel("FPGA")
  71. if self.adc_number > 4:
  72. self.thdelayLabel_2 = self.createLabel("T/H FMC2")
  73. self.labelCoarseAdcDelay_2 = self.createLabel("ADC FMC2")
  74. #self.labelCoarseFpgaDelay_2 = self.createLabel("FPGA FMC2")
  75. self.labelCascade = self.createLabel("Cascade")
  76. self.coarseLabel = self.createLabel(tr("Label", "330ps Coarse Delay"))
  77. self.coarseInputTh = self.createSpinbox(0, self.board_config.get('delay_330_max'), connect=lambda: update_delay("delay_330_th", "coarseInputTh"))
  78. self.coarseInputAdc = self.createSpinbox(0, self.board_config.get('delay_330_max'), connect=lambda: update_delay("delay_330_adc", "coarseInputAdc"))
  79. self.coarseInputFpga = self.createSpinbox(0, self.board_config.get('delay_330_max'), connect=lambda: update_delay("delay_330_fpga", "coarseInputFpga"))
  80. Elements.addItem(["timing_{}".format(self.board_id), "no_board_{}".format(self.board_id), "acquire_{}".format(self.board_id), "continuous_read_{}".format(board_id)],
  81. [
  82. #self.coarseInputFpga,
  83. #self.coarseInputAdc,
  84. self.coarseInputTh
  85. ]
  86. )
  87. #self.coarseInputAdc.setEnabled(False)
  88. #self.coarseInputFpga.setEnabled(False)
  89. if self.board_config.is_KAPTURE2():
  90. self.coarse2Label = self.createLabel(tr("Label", "25ps Coarse Delay"))
  91. self.coarse2InputTh = self.createSpinbox(0, self.board_config.get('delay_25_max'), connect=lambda: update_delay("delay_25_th", "coarse2InputTh"))
  92. self.coarse2InputAdc = self.createSpinbox(0, self.board_config.get('delay_25_max'), connect=lambda: update_delay("delay_25_adc", "coarse2InputAdc"))
  93. self.coarse2InputFpga = self.createSpinbox(0, self.board_config.get('delay_25_max'), connect=lambda: update_delay("delay_25_fpga", "coarse2InputFpga"))
  94. Elements.addItem(["timing_{}".format(self.board_id), "no_board_{}".format(self.board_id), "acquire_{}".format(self.board_id), "continuous_read_{}".format(board_id)],
  95. [
  96. #self.coarse2InputAdc,
  97. #self.coarse2InputFpga,
  98. self.coarse2InputTh
  99. ]
  100. )
  101. self.adc1CoarseInputSwitch = self.createCheckbox(tr("Label", "Enable advanced"), connect=self.toggleAdvanced)
  102. if self.adc_number > 4:
  103. #self.coarseLabel_2 = self.createLabel(tr("Label", "330ps FMC2"))
  104. self.coarseInputTh_2 = self.createSpinbox(0, self.board_config.get('delay_330_max'), connect=lambda: update_delay("delay_330_th_2", "coarseInputTh_2"))
  105. self.coarseInputAdc_2 = self.createSpinbox(0, self.board_config.get('delay_330_max'), connect=lambda: update_delay("delay_330_adc_2", "coarseInputAdc_2"))
  106. #self.coarseInputFpga_2 = self.createSpinbox(0, self.board_config.get('delay_330_max'), connect=lambda: update_delay("delay_330_fpga_2", "coarseInputFpga_2"))
  107. #self.coarse2Label = self.createLabel(tr("Label", "25ps FMC2"))
  108. self.coarse2InputTh_2 = self.createSpinbox(0, self.board_config.get('delay_25_max'), connect=lambda: update_delay("delay_25_th_2", "coarse2InputTh_2"))
  109. self.coarse2InputAdc_2 = self.createSpinbox(0, self.board_config.get('delay_25_max'), connect=lambda: update_delay("delay_25_adc_2", "coarse2InputAdc_2"))
  110. #self.coarse2InputFpga_2 = self.createSpinbox(0, self.board_config.get('delay_25_max'), connect=lambda: update_delay("delay_25_fpga_2", "coarse2InputFpga_2"))
  111. self.coarseInputCascade = self.createSpinbox(0, self.board_config.get('delay_cascade_max'), connect=lambda: update_delay("delay_cascade", "coarseInputCascade"))
  112. self.coarse2InputCascade = self.createSpinbox(0, self.board_config.get('delay_25_max'), connect=lambda: update_delay("delay_cascade_25", "coarse2InputCascade"))
  113. Elements.addItem(["timing_{}".format(self.board_id), "no_board_{}".format(self.board_id), "acquire_{}".format(self.board_id), "continuous_read_{}".format(board_id)],
  114. [
  115. #self.coarseInputFpga,
  116. #self.coarseInputAdc,
  117. #self.coarseInputTh_2,
  118. #self.coarse2InputAdc,
  119. #self.coarse2InputFpga,
  120. self.coarse2InputTh_2
  121. ]
  122. )
  123. self.fineLabel = self.createLabel(tr("Label", "Fine Delay"))
  124. self.fineAdcInput = []
  125. for i in range(self.adc_number):
  126. self.fineAdcInput.append(self.createSpinbox(0, 31, connect=self.on_adc_delay_changed))
  127. #---------[ End ]---------
  128. Elements.addItem(["timing_{}".format(self.board_id), "no_board_{}".format(self.board_id), "acquire_{}".format(self.board_id), "continuous_read_{}".format(board_id)], self.fineAdcInput)
  129. def setValueSilent(value, spinbox, adc):
  130. '''set values silent to not trigger signals'''
  131. spinbox.blockSignals(True)
  132. if adc is None:
  133. spinbox.setValue(value)
  134. else:
  135. spinbox.setValue(value[adc])
  136. spinbox.blockSignals(False)
  137. # --------[ Set observers ]------------
  138. def obs(who, what, adc=None):
  139. '''observe something'''
  140. board.get_board_config(board_id).observe(
  141. who,
  142. lambda value=None: setValueSilent(value=value, spinbox=who, adc=adc),
  143. what
  144. )
  145. for i, item in enumerate(self.fineAdcInput):
  146. obs(item, 'chip_delay', i)
  147. obs(self.coarseInputTh, 'delay_330_th')
  148. obs(self.coarseInputAdc, 'delay_330_adc')
  149. obs(self.coarseInputFpga, 'delay_330_fpga')
  150. if self.board_config.is_KAPTURE2():
  151. obs(self.coarse2InputTh, 'delay_25_th')
  152. obs(self.coarse2InputAdc, 'delay_25_adc')
  153. obs(self.coarse2InputFpga, 'delay_25_fpga')
  154. if self.adc_number > 4:
  155. obs(self.coarseInputTh_2, 'delay_330_th_2')
  156. obs(self.coarseInputAdc_2, 'delay_330_adc_2')
  157. #obs(self.coarseInputFpga_2, 'delay_330_fpga_2')
  158. obs(self.coarseInputCascade, 'delay_cascade')
  159. obs(self.coarse2InputTh_2, 'delay_25_th_2')
  160. obs(self.coarse2InputAdc_2, 'delay_25_adc_2')
  161. obs(self.coarse2InputCascade, 'delay_cascade_25')
  162. #obs(self.coarse2InputFpga_2, 'delay_25_fpga_2')
  163. #obs(self.adc1CoarseInput, 'adc_1_delay_individual')
  164. # -------[ Create outputs ]---------------
  165. self.totalLabel = self.createLabel(tr("Label", "Total Delay"))
  166. self.totalAdcBox = []
  167. for i in range(self.adc_number):
  168. self.totalAdcBox.append(self.createInput("", read_only=True))
  169. self.totalAdcBoxCalib = []
  170. for i in range(self.adc_number):
  171. self.totalAdcBoxCalib.append(self.createInput("", read_only=True))
  172. self.board_config.observe(self.totalAdcBox[0], self.delay_observer, 'chip_delay')
  173. self.board_config.observe(self.totalAdcBox[0], self.delay_observer, 'delay_330_th')
  174. if self.board_config.is_KAPTURE2():
  175. self.board_config.observe(self.totalAdcBox[0], self.delay_observer, 'delay_25_th')
  176. if self.adc_number > 4:
  177. self.board_config.observe(self.totalAdcBox[0], self.delay_observer, 'delay_330_th_2')
  178. self.board_config.observe(self.totalAdcBox[0], self.delay_observer, 'delay_25_th_2')
  179. #--------[ Fill Grid ]----------------
  180. self.layout.addWidget(self.thdelayLabel, 0, 1)
  181. self.layout.addWidget(self.labelCoarseAdcDelay, 0, 2)
  182. self.layout.addWidget(self.labelCoarseFpgaDelay, 0, 3)
  183. if self.board_config.is_KAPTURE2():
  184. self.layout.addWidget(self.adc1CoarseInputSwitch, 0, 8,1,2)
  185. if self.adc_number > 4:
  186. self.layout.addWidget(self.thdelayLabel_2, 0, 4)
  187. self.layout.addWidget(self.labelCoarseAdcDelay_2, 0, 5)
  188. #self.layout.addWidget(self.labelCoarseFpgaDelay_2, 0, 6)
  189. self.layout.addWidget(self.labelCascade, 0, 7)
  190. self.layout.addWidget(self.coarseLabel, 1, 0)
  191. self.layout.addWidget(self.coarseInputTh, 1, 1)
  192. self.layout.addWidget(self.coarseInputAdc, 1, 2)
  193. self.layout.addWidget(self.coarseInputFpga, 1, 3)
  194. #self.layout.addWidget(self.adc1thdelayLabel, 0, 2)
  195. #self.layout.addWidget(self.adc1CoarseInput, 1, 2)
  196. #self.layout.addWidget(self.adc1CoarseInputSwitch, 1, 3, 1, 2)
  197. self.layout.addItem(QtGui.QSpacerItem(10, 15), 2, 1)
  198. if self.board_config.is_KAPTURE2():
  199. self.layout.addWidget(self.coarse2Label, 3, 0)
  200. self.layout.addWidget(self.coarse2InputTh, 3, 1)
  201. self.layout.addWidget(self.coarse2InputAdc, 3, 2)
  202. self.layout.addWidget(self.coarse2InputFpga, 3, 3)
  203. if self.adc_number > 4:
  204. self.layout.addWidget(self.coarseInputTh_2, 1, 4)
  205. self.layout.addWidget(self.coarseInputAdc_2, 1, 5)
  206. #self.layout.addWidget(self.coarseInputFpga_2, 1, 6)
  207. self.layout.addWidget(self.coarseInputCascade, 1, 7)
  208. self.layout.addWidget(self.coarse2InputTh_2, 3, 4)
  209. self.layout.addWidget(self.coarse2InputAdc_2, 3, 5)
  210. #self.layout.addWidget(self.coarse2InputFpga_2, 3, 6)
  211. self.layout.addWidget(self.coarse2InputCascade, 3, 7)
  212. self.layout.addItem(QtGui.QSpacerItem(10, 15), 4, 1)
  213. # Leave some rows free for additional things (empty rows will not be shown)
  214. for i in range(self.adc_number):
  215. self.layout.addWidget(self.createLabel("ADC "+str(i+1)), 5, i+1)
  216. self.layout.addWidget(self.fineLabel, 6, 0)
  217. for i, item in enumerate(self.fineAdcInput):
  218. self.layout.addWidget(item, 6, i+1)
  219. self.layout.addItem(QtGui.QSpacerItem(10, 15), 7, 1)
  220. line = QtGui.QFrame()
  221. line.setFrameStyle(QtGui.QFrame.HLine)
  222. self.layout.addWidget(line, 8, 0, 1, 0)
  223. self.layout.addItem(QtGui.QSpacerItem(10, 15), 9, 1)
  224. self.layout.addWidget(self.totalLabel, 10, 0)
  225. for i, item in enumerate(self.totalAdcBox):
  226. self.layout.addWidget(item, 10, i+1)
  227. item.setFocusPolicy(QtCore.Qt.ClickFocus)
  228. self.layout.addWidget(self.createLabel('Calibrated (ps)'), 11, 0)
  229. for i, item in enumerate(self.totalAdcBoxCalib):
  230. self.layout.addWidget(item, 11, i+1)
  231. self.layout.addItem(QtGui.QSpacerItem(10, 15), 11, 1)
  232. self.board_config.notify_all_observers()
  233. self.toggleAdvanced()
  234. self.setWindowTitle(tr("Heading", "Timing"))
  235. def delay_observer(self, x):
  236. d330 = ['delay_330_th', 'delay_330_th']
  237. d25 = ['delay_25_th', 'delay_25_th']
  238. for i, item in enumerate(self.totalAdcBox):
  239. if self.board_config.is_KAPTURE2():
  240. string = '%i + %i + %i' % (self.board_config.get(d330[i//4]) * self.board_config.get('delay_330_factor'),
  241. self.board_config.get(d25[i//4]) * self.board_config.get('delay_25_factor'),
  242. (self.board_config.get('chip_delay')[i]) * self.board_config.get('chip_delay_factor'))
  243. if i < 4:
  244. string += "+ {:d}".format(self.board_config.get("delay_330_th_2") * self.board_config.get('delay_330_factor')
  245. + (self.board_config.get("delay_25_th_2")- self.board_config.get("default_25_th_2")) * self.board_config.get('delay_25_factor'))
  246. item.setText(string)
  247. val = self.board_config.get(d25[i//4]) * self.board_config.get('delay_25_factor')+self.board_config.get('chip_delay')[i] * self.board_config.get('chip_delay_factor')
  248. if val == self.board_config.get('delay_330_factor'):
  249. item.setStyleSheet("color: rgb(120, 80, 0);")
  250. elif val > self.board_config.get('delay_330_factor'):
  251. item.setStyleSheet("color: rgb(200, 80, 0);")
  252. else:
  253. item.setStyleSheet("color: rgb(0, 0, 0);")
  254. else:
  255. item.setText('%i + %i' % (self.board_config.get('delay_330_th') * self.board_config.get('delay_330_factor'),
  256. self.board_config.get('chip_delay')[i] * self.board_config.get('chip_delay_factor')))
  257. if self.board_config.is_KAPTURE2():
  258. for i, item in enumerate(self.totalAdcBoxCalib):
  259. value = theCalibration.calibrateX(i, self.board_config.get('delay_330_th'), self.board_config.get('delay_25_th'), self.board_config.get('chip_delay')[i], self.board_config.get("delay_25_th_2"))
  260. item.setText('{}'.format(np.round(value*1e12,1)))
  261. """
  262. if self.fileHandle is not None:
  263. for i, item in enumerate(self.totalAdcBoxCalib):
  264. item.setText('{:.1f}'.format(self.board_config.get(d330[i//4]) * self.xcalib['d330'][()] + self.xcalib[str(i)]['33'][int(self.board_config.get(d330[i//4]))] +
  265. self.board_config.get(d25[i//4]) * self.xcalib['d25'][()] + self.xcalib[str(i)]['25'][int(self.board_config.get(d25[i//4]))] +
  266. self.board_config.get('chip_delay')[i]* self.xcalib['d3'][()] + self.xcalib[str(i)]['3'][int(self.board_config.get('chip_delay')[i])] -
  267. float(self.fileHandle['x'][str(i)]['offset'][()])*1e12
  268. ))
  269. else:
  270. for i, item in enumerate(self.totalAdcBoxCalib):
  271. value = (self.board_config.get(d330[i//4]) * self.board_config.get('delay_330_factor')
  272. + self.board_config.get(d25[i//4]) * self.board_config.get('delay_25_factor')
  273. + (self.board_config.get('chip_delay')[i]) * self.board_config.get('chip_delay_factor'))
  274. if i>=4:
  275. value -= (self.board_config.get("delay_330_th_2") * self.board_config.get('delay_330_factor')
  276. + self.board_config.get("delay_25_th_2") * self.board_config.get('delay_25_factor'))
  277. item.setText(str(value))
  278. """
  279. def toggleAdvanced(self):
  280. if self.show_advanced:
  281. self.labelCoarseAdcDelay.setEnabled(False)
  282. self.labelCoarseFpgaDelay.setEnabled(False)
  283. self.coarseInputAdc.setEnabled(False)
  284. self.coarseInputFpga.setEnabled(False)
  285. if self.board_config.is_KAPTURE2():
  286. self.coarse2InputAdc.setEnabled(False)
  287. self.coarse2InputFpga.setEnabled(False)
  288. if self.adc_number > 4:
  289. self.labelCoarseAdcDelay_2.setEnabled(False)
  290. #self.labelCoarseFpgaDelay_2.setEnabled(False)
  291. self.labelCascade.setEnabled(False)
  292. self.coarseInputTh_2.setEnabled(False)
  293. self.coarseInputAdc_2.setEnabled(False)
  294. #self.coarseInputFpga_2.setEnabled(False)
  295. self.coarse2InputAdc_2.setEnabled(False)
  296. #self.coarse2InputFpga_2.setEnabled(False)
  297. self.coarseInputCascade.setEnabled(False)
  298. self.coarse2InputCascade.setEnabled(False)
  299. self.show_advanced = False
  300. else:
  301. self.labelCoarseAdcDelay.setEnabled(True)
  302. self.labelCoarseFpgaDelay.setEnabled(True)
  303. self.coarseInputAdc.setEnabled(True)
  304. self.coarseInputFpga.setEnabled(True)
  305. if self.board_config.is_KAPTURE2():
  306. self.coarse2InputAdc.setEnabled(True)
  307. self.coarse2InputFpga.setEnabled(True)
  308. if self.adc_number > 4:
  309. self.labelCoarseAdcDelay_2.setEnabled(True)
  310. #self.labelCoarseFpgaDelay_2.setEnabled(True)
  311. self.labelCascade.setEnabled(True)
  312. self.coarseInputTh_2.setEnabled(True)
  313. self.coarseInputAdc_2.setEnabled(True)
  314. #self.coarseInputFpga_2.setEnabled(True)
  315. self.coarse2InputAdc_2.setEnabled(True)
  316. #self.coarse2InputFpga_2.setEnabled(True)
  317. self.coarseInputCascade.setEnabled(True)
  318. self.coarse2InputCascade.setEnabled(True)
  319. self.show_advanced = True
  320. def toggleAdc1IndividualDelay(self):
  321. """
  322. Toggle to use an individual delay for adc1 or not
  323. :return: -
  324. """
  325. self.adc1CoarseInput.setEnabled(self.adc1CoarseInputSwitch.checkState())
  326. if not self.adc1CoarseInput.isEnabled():
  327. board.get_board_config(self.board_id).update('adc_1_delay_individual', -1) # Be careful this does no silent update
  328. def setValueSilent(self, element, value):
  329. """
  330. Set Values to inputs without notifying observers
  331. :param element: the input
  332. :param value: the value
  333. :return: -
  334. """
  335. element.blockSignals(True)
  336. element.setValue(value)
  337. element.blockSignals(False)
  338. def closeEvent(self, event):
  339. """
  340. Event handler when this window is closed
  341. """
  342. self.board_config.unobserve(self.totalAdcBox[0], 'chip_delay')
  343. if self.board_config.is_KAPTURE2():
  344. self.board_config.unobserve(self.totalAdcBox[0], 'delay_25_th')
  345. if self.adc_number > 4:
  346. self.board_config.unobserve(self.totalAdcBox[0], 'delay_330_th_2')
  347. self.board_config.unobserve(self.totalAdcBox[0], 'delay_25_th_2')
  348. self.board_config.unobserve(self.totalAdcBox[0], 'delay_330_th')
  349. for i, item in enumerate(self.fineAdcInput):
  350. self.board_config.unobserve(item, 'chip_delay')
  351. self.board_config.unobserve(self.coarseInputTh, 'delay_330_th')
  352. self.board_config.unobserve(self.coarseInputAdc, 'delay_330_adc')
  353. self.board_config.unobserve(self.coarseInputFpga, 'delay_330_fpga')
  354. if self.board_config.is_KAPTURE2():
  355. self.board_config.unobserve(self.coarse2InputTh, 'delay_25_th')
  356. self.board_config.unobserve(self.coarse2InputAdc, 'delay_25_adc')
  357. self.board_config.unobserve(self.coarse2InputFpga, 'delay_25_fpga')
  358. if self.adc_number > 4:
  359. self.board_config.unobserve(self.coarseInputTh_2, 'delay_330_th_2')
  360. self.board_config.unobserve(self.coarseInputAdc_2, 'delay_330_adc_2')
  361. #self.board_config.unobserve(self.coarseInputFpga_2, 'delay_330_fpga_2')
  362. self.board_config.unobserve(self.coarseInputCascade, 'delay_cascade')
  363. self.board_config.unobserve(self.coarse2InputTh_2, 'delay_25_th_2')
  364. self.board_config.unobserve(self.coarse2InputAdc_2, 'delay_25_adc_2')
  365. self.board_config.unobserve(self.coarse2InputCascade, 'delay_cascade_25')
  366. #self.board_config.unobserve(self.coarse2InputFpga_2, 'delay_25_fpga_2')
  367. Elements.emptyGroup('timing_{}'.format(self.board_id))
  368. Elements.removeItem(None, self.fineAdcInput)
  369. Elements.removeItem(None, [
  370. self.coarseInputTh,
  371. self.coarseInputAdc,
  372. self.coarseInputFpga
  373. ]
  374. )
  375. if self.board_config.is_KAPTURE2():
  376. Elements.removeItem(None, [
  377. self.coarse2InputTh,
  378. self.coarse2InputAdc,
  379. self.coarse2InputFpga
  380. ]
  381. )
  382. if self.adc_number > 4:
  383. Elements.removeItem(None, [
  384. self.coarseInputTh_2,
  385. self.coarseInputAdc_2,
  386. #self.coarseInputFpga_2,
  387. self.coarse2InputTh_2,
  388. self.coarse2InputAdc_2,
  389. #self.coarse2InputFpga_2
  390. ]
  391. )
  392. super(TimingPart, self).closeEvent(event)
  393. def on_adc_delay_changed(self):
  394. """
  395. Handler that gets called when an adc delay gets changed
  396. """
  397. try:
  398. factors = []
  399. for item in self.fineAdcInput:
  400. factors.extend([item.value()])
  401. self.board_config.update('chip_delay', factors)
  402. except board.BoardError as e:
  403. logging.error("ADC fine delay failed: {}".format(str(e)))
  404. bif.bk_status_readout(self.board_id)
  405. return
  406. # 888 d8b d8b 888 888d8b 888 888
  407. # 888 Y8P Y8P 888 o 888Y8P 888 888
  408. # 888 888 d8b 888 888 888
  409. # 88888888888888b.d88b. 88888888b. .d88b. 888 d888b 888888 .d88888 .d88b. .d88b. 888888
  410. # 888 888888 "888 "88b888888 "88bd88P"88b888d88888b888888d88" 888d88P"88bd8P Y8b888
  411. # 888 888888 888 888888888 888888 88888888P Y88888888888 888888 88888888888888
  412. # Y88b. 888888 888 888888888 888Y88b 8888888P Y8888888Y88b 888Y88b 888Y8b. Y88b.
  413. # "Y888888888 888 888888888 888 "Y88888888P Y888888 "Y88888 "Y88888 "Y8888 "Y888
  414. # 888 888
  415. # Y8b d88P Y8b d88P
  416. # "Y88P" "Y88P"
  417. class TimingWidget(kcgw.KCGWidgets):
  418. """
  419. This is the container that holds the tab widget which contains the timing widgets for each board
  420. """
  421. def __init__(self, unique_id, parent=None):
  422. super(TimingWidget, self).__init__()
  423. self.id = unique_id
  424. self.par = parent
  425. self.setWindowTitle("Timing")
  426. self.layout = QtGui.QHBoxLayout()
  427. self.setLayout(self.layout)
  428. self.widgets = {i: TimingPart(i, self) for i in available_boards} # has to set parent with self because
  429. # otherwise the window does not get resized correctly upon enabling timescan
  430. if available_boards.multi_board:
  431. self.tabWidget = QtGui.QTabWidget()
  432. self.layout.addWidget(self.tabWidget)
  433. for id, widget in self.widgets.items():
  434. self.tabWidget.addTab(widget, available_boards.get_board_name_from_id(id))
  435. else:
  436. self.single_board_widget = list(self.widgets.values())[0]
  437. self.layout.addWidget(self.single_board_widget)
  438. def adjustSizeForTimeScan(self):
  439. """
  440. Adjust the size of the widget to accomodate the time_scan part
  441. :return:
  442. """
  443. # self.parentWindow = self.parent().parent().parent().parent() # one up is stacked widget, second up is
  444. # tab widget, third up is timingWidget fourh up is KCGWSubWindow (the actual window)
  445. QtCore.QCoreApplication.processEvents()
  446. if self.parent().windowState() & QtCore.Qt.WindowMaximized:
  447. self.parent().setWindowState(QtCore.Qt.WindowMaximized)
  448. else:
  449. # self.parent().resize(self.minimumSizeHint().width() * 1.2, self.minimumSizeHint().height()*1.1)
  450. self.parent().adjustSize()
  451. def closeEvent(self, event):
  452. global __widget_id__
  453. __widget_id__ = None
  454. for widget in list(self.widgets.values()):
  455. widget.closeEvent(event)
  456. del self.par.widgets[self.id]
  457. super(TimingWidget, self).closeEvent(event)
  458. def addTimingWidget():
  459. """
  460. Add this widget to the gui.
  461. This function will actually open the subwindow.
  462. :return: -
  463. """
  464. global __widget_id__
  465. if __widget_id__:
  466. global_objects.get_global('area').widgets[__widget_id__].setFocus()
  467. else:
  468. nid = kcgw.idg.genid()
  469. __widget_id__ = nid
  470. w = TimingWidget(nid, global_objects.get_global('area'))
  471. global_objects.get_global('area').newWidget(w, tr("Heading", "Timing"), nid, widget_type=4, minSize=True) #TODO: proper type
  472. kcgw.register_widget(QtGui.QIcon(config.icon_path(config.timingIcon)), tr("Heading", "Timing"), addTimingWidget, "Ctrl+T")