TimescanWidget.py 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411
  1. from __future__ import print_function
  2. from PyQt4 import QtGui, QtCore
  3. from PyQt4.QtCore import pyqtSlot
  4. import pyqtgraph as pg
  5. from PyQt4.QtGui import QFont, QTableWidget
  6. from scipy.optimize import curve_fit
  7. from scipy.stats import chisquare
  8. from scipy.stats import chi2_contingency
  9. from scipy.special import erfc, erf
  10. import copy
  11. from ..base import kcgwidget as kcgw
  12. from ..base.backend import board
  13. from ..base.backend.DataSet import DataSet
  14. from ..base.backend.TimeScan import TimeScan
  15. from ..base.backend.board import available_boards
  16. from ..base import backendinterface as bif
  17. from ..base.groupedelements import Elements, live_plot_windows
  18. from ..base.globals import glob as global_objects
  19. from .. import config
  20. from ..config import colours, coloursTrans
  21. from ..base import storage
  22. from ..base.backend.CalibrationHandle import theCalibration
  23. from . import UpdateCalibrationWidget
  24. from . import CorrelationWidget
  25. import logging
  26. import time
  27. from time import sleep
  28. import h5py
  29. import traceback
  30. import numpy as np
  31. import os
  32. __widget_id__ = None
  33. MODE_ALL = 0
  34. MODE_THREASHOLD = 1
  35. MODE_AUTOBUCKET = 2
  36. MODE_AUTOBUCKET_TMP_THRESHOLD = 3
  37. MODE_BUCKET = 4
  38. MODE_BUCKET_THRESHOLD = 5
  39. MODE_ALL_BUCKETS = 6
  40. class ScanThread(QtCore.QObject):
  41. '''Timescan Thread class'''
  42. pbarSignal = QtCore.pyqtSignal(object, float)
  43. stopSignal = QtCore.pyqtSignal(object, str)
  44. plotSignal = QtCore.pyqtSignal(object)
  45. def __init__(self, c_min, c_max, f_min, f_max, board_id, index, info, outdir="", threshold=0, saveraw=False, c25_min=-1, c25_max=-1, step4=False, meanMode=MODE_ALL, fastMode=False, calibScan=False):
  46. super(ScanThread, self).__init__()
  47. self.c_min = c_min
  48. self.c_max = c_max
  49. self.f_min = f_min
  50. self.f_max = f_max
  51. self.c25_min = c25_min
  52. self.c25_max = c25_max
  53. self.step4 = step4
  54. self.board_id = board_id
  55. self.threshold = threshold
  56. self.index = index
  57. self.info = info
  58. self.saveraw = saveraw
  59. self.rawdir = ""
  60. self.outdir = outdir
  61. self.adc_number = board.get_board_config(self.board_id).get('adc_number')
  62. self.board_config = board.get_board_config(self.board_id)
  63. self.timescan = TimeScan()
  64. self.stop = False
  65. self.timestamp = 0
  66. self.meanMode = meanMode
  67. self.buckets = None
  68. self.fastMode = fastMode
  69. self.calibrationScan = calibScan
  70. def setDelay(self, value):
  71. board.get_board_config(self.board_id).update('delay_330_th', value)
  72. board.get_board_config(self.board_id).update('delay_330_th_2', value)
  73. def setDelay25(self, value):
  74. board.get_board_config(self.board_id).update('delay_25_th', value)
  75. board.get_board_config(self.board_id).update('delay_25_th_2', value)
  76. def setDelayB(self, value):
  77. board.get_board_config(self.board_id).update('delay_330_th_2', value)
  78. def setDelayB25(self, value):
  79. board.get_board_config(self.board_id).update('delay_25_th_2', value)
  80. def setFineDelay(self, value):
  81. board.get_board_config(self.board_id).update('chip_delay', [value,value,value,value,value,value,value,value])
  82. def scan(self):
  83. print('##################################################################')
  84. self.stop = False
  85. self.timestamp = time.time()
  86. self.timescan.prepare(self.adc_number, self.meanMode==MODE_ALL_BUCKETS)
  87. if self.fastMode:
  88. print('fastMode')
  89. self.board_config.update('chip_delay', [0,10,20,30,0,10,20,30])
  90. if self.saveraw or self.meanMode in [MODE_AUTOBUCKET_TMP_THRESHOLD, MODE_AUTOBUCKET]:
  91. self.saveraw = True
  92. self.rawdir = os.path.join(self.outdir, 'raw')#, '{:02d}_{:.3f}'.format(self.index, self.timestamp))
  93. self.rawfilename = os.path.join(self.rawdir, '{:02d}_{:.3f}.hdf'.format(self.index, self.timestamp))
  94. if not os.path.isdir(self.rawdir):
  95. os.makedirs(self.rawdir)
  96. self.rawFile = h5py.File(self.rawfilename, 'w')
  97. self.dataGroup = self.rawFile.create_group('data')
  98. for c_step in range(self.c_min, self.c_max+1):
  99. self.setDelay(c_step)
  100. sleep(0.1)
  101. step = 1
  102. if self.step4:
  103. step=4
  104. for c25_step in range(self.c25_min, self.c25_max+1, step):
  105. if board.get_board_config(self.board_id).is_KAPTURE2():
  106. self.setDelay25(c25_step)
  107. if self.calibrationScan:
  108. #self.setDelayB(0)
  109. self.setDelayB25(4)
  110. c25_step_b = 4
  111. pass
  112. c25_step_b = board.get_board_config(self.board_id).get('delay_25_th_2')
  113. for f_step in range(self.f_min, self.f_max+1):
  114. if not self.fastMode:
  115. self.setFineDelay(f_step)
  116. self.startTime = time.time()
  117. print('--------------------------------------------------------')
  118. print('{:4.3f} step'.format(time.time()))
  119. if not kcgw.testing:
  120. sleep(0.25)
  121. else:
  122. sleep(0.05)
  123. if self.stop:
  124. self.finished(c_step, c25_step, f_step)
  125. return
  126. self.readData(c_step, c25_step, f_step, 0, c25_step_b)
  127. #for f_step
  128. if self.calibrationScan:
  129. self.setFineDelay(0)
  130. f_step = 0
  131. self.setDelayB(0)
  132. c_step_b = 0
  133. for c25_step_b in range(1, 8+1):
  134. self.setDelayB25(c25_step_b)
  135. print('--------------------------------------------------------')
  136. print('{:4.3f} step'.format(time.time()))
  137. if not kcgw.testing:
  138. sleep(0.25)
  139. else:
  140. sleep(0.05)
  141. if self.stop:
  142. self.finished(c_step, c25_step, f_step)
  143. return
  144. self.readData(c_step, c25_step, f_step, c_step_b, c25_step_b)
  145. #if calibrationScan
  146. #for c25_step
  147. #for c_step
  148. self.finished(c_step, c25_step, f_step)
  149. def readData(self, c_step, c25_step, f_step, c_step_b=0, c25_step_b=0):
  150. try:
  151. # -----------[ IMPORTANT ]---------------------
  152. if not kcgw.testing:
  153. data_raw = np.fromstring(bif._bif_read_data(self.board_id, True), dtype=np.uint32)
  154. if data_raw is None:
  155. print('no data returned')
  156. self.stop = True
  157. self.finished(c_step, c25_step, f_step)
  158. return
  159. # ----------------------------------------------
  160. else:
  161. f_name = "t/1544038883.603.out"#1529502127.686.out"
  162. data_raw = np.memmap(f_name, dtype='uint32')
  163. data = DataSet(rawData=data_raw, tRev=config.tRev, bunchesPerTurn=config.bunches_per_turn, shiftFMC2=config.shiftFMC2)
  164. #print('{:4.3f} emit Plot'.format(time.time()-self.startTime))
  165. self.plotSignal.emit(data)
  166. #print('{:4.3f} emit Plot done'.format(time.time()-self.startTime))
  167. except Exception as e:
  168. print(e)
  169. self.stop = True
  170. self.finished(c_step, c25_step, f_step)
  171. return
  172. if self.saveraw:
  173. self.dataGroup.create_dataset(
  174. "{:02d}_{:02d}_{:02d}_{:02d}_{:02d}".format(c_step, c25_step, f_step, c_step_b, c25_step_b),
  175. data=data_raw, dtype='uint32',
  176. shuffle=False, chunks=(2**8,4),
  177. compression='lzf'
  178. )
  179. baseline = 2048
  180. tmpmeans=[0,0,0,0,0,0,0,0]
  181. for adc in range(self.adc_number):
  182. try:
  183. tmp = data.array[:,adc]
  184. except Exception as e:
  185. print(e)
  186. self.stop = True
  187. self.finished(c_step, c25_step, f_step)
  188. return
  189. #print('{:4.3f} Calc ADC {} '.format(time.time()-self.startTime, adc))
  190. if self.meanMode in [MODE_THREASHOLD]:
  191. if self.threshold > 0:
  192. tmp = tmp[np.where((tmp > (baseline)+self.threshold))]# | (tmp < baseline-self.threshold))]
  193. else:
  194. tmp = tmp[np.where((tmp < (baseline)+self.threshold))]# | (tmp < baseline-self.threshold))]
  195. #print('{:4.3f} MODE_THREASHOLD done'.format(time.time()-self.startTime))
  196. elif self.meanMode in [MODE_BUCKET]:
  197. tmp = tmp[self.threshold::184]
  198. #print('{:4.3f} MODE_BUCKET done'.format(time.time()-self.startTime))
  199. elif self.meanMode in [MODE_ALL_BUCKETS]:
  200. tmp = np.reshape(tmp, (-1,184))
  201. if len(tmp) < 5:
  202. tmp=[baseline,baseline]
  203. mean = np.mean(tmp,0)
  204. std = np.std(tmp,0)
  205. self.timescan.appendData(mean,std,adc, c_step, c25_step, f_step, c25_step_b)
  206. #print('{:4.3f} emit pbar'.format(time.time()-self.startTime))
  207. tmpScan = copy.deepcopy(self.timescan)
  208. self.pbarSignal.emit(tmpScan,
  209. ((c_step-self.c_min)*(self.c25_max-self.c25_min+1.0) * (self.f_max-self.f_min+1.0) + (c25_step-self.c25_min)*(self.f_max-self.f_min+1.0) + (f_step-self.f_min))/
  210. ((self.c_max-self.c_min+1.0) * (self.c25_max-self.c25_min+1.0) * (self.f_max-self.f_min+1.0))
  211. )
  212. #print('{:4.3f} emit pbar done'.format(time.time()-self.startTime))
  213. def finished(self, c_step=0, c25_step=0, f_step=0):
  214. '''Method to handle the end of the thread'''
  215. if self.saveraw:
  216. grp = self.rawFile.create_group('info')
  217. grp['Nr'] = self.index
  218. grp['Info'] = '{}'.format(self.info)
  219. grp['Threshold'] = self.threshold
  220. grp['T/H'] = [self.c_min, self.c_max]
  221. grp['25ps'] = [self.c25_min, self.c25_max]
  222. grp['fine'] = [self.f_min, self.f_max]
  223. grp['Step4'] = self.step4
  224. grp['Mode'] = self.meanMode
  225. grp['stop'] = [c_step, c25_step, f_step]
  226. grp['fastMode'] = self.fastMode
  227. grp['Calibration'] = self.calibrationScan
  228. self.rawFile.close()
  229. file= '{:02d}_{:0.3f}.scan'.format(self.index, self.timestamp)
  230. filename = os.path.join(self.outdir, file)
  231. self.timescan.saveScan(filename, self.index, self.info, self.threshold,
  232. self.c_min, self.c_max, self.c25_min, self.c25_max,
  233. self.f_min, self.f_max, self.stop, c_step, c25_step, f_step,
  234. self.step4, self.meanMode, self.fastMode, self.calibrationScan)
  235. board.get_board_status(self.board_id).time_scan = False
  236. self.stop = True
  237. self.stopSignal.emit(self.timescan, filename)
  238. return
  239. # 8888888b. 888 888 888 888 d8b 888 888
  240. # 888 Y88b 888 888 888 o 888 Y8P 888 888
  241. # 888 888 888 888 888 d8b 888 888 888
  242. # 888 d88P 888 .d88b. 888888 888 d888b 888 888 .d88888 .d88b. .d88b. 888888
  243. # 8888888P" 888 d88""88b 888 888d88888b888 888 d88" 888 d88P"88b d8P Y8b 888
  244. # 888 888 888 888 888 88888P Y88888 888 888 888 888 888 88888888 888
  245. # 888 888 Y88..88P Y88b. 8888P Y8888 888 Y88b 888 Y88b 888 Y8b. Y88b.
  246. # 888 888 "Y88P" "Y888 888P Y888 888 "Y88888 "Y88888 "Y8888 "Y888
  247. # 888
  248. # Y8b d88P
  249. # "Y88P"
  250. LINEAR = 0
  251. GAUSS = 1
  252. EGAUSS = 2
  253. EGAUSSB= 3
  254. SKEW = 4
  255. SINUS = 5
  256. __timing_plot_widget_id__ = {}
  257. __timing_plot_widget__ = None
  258. __datastorage__ = None
  259. ##################################################################################
  260. class ScanPlotWidget(kcgw.KCGWidgets):
  261. """
  262. The Timescan result plot subwindow.
  263. """
  264. def __init__(self, unique_id, board_id, parent=None):
  265. """
  266. Initialises the timing plot window
  267. :param unique_id: the id for this window
  268. :param parent: parent object
  269. :return: -
  270. """
  271. super(ScanPlotWidget, self).__init__()
  272. self.id = unique_id
  273. self.par = parent
  274. self.board_id = board_id
  275. self.timeScan = None
  276. #self.block = False
  277. # ------[ Variable declaration ]------------
  278. self.xrange = (0, 1) #T/H
  279. self.yrange = (0, 1) #fine
  280. self.zrange = (0, 1) #25ps
  281. self.x = 1 # Number of Ticks in the x-direction This is set by the gui programmatically
  282. self.y = 1 # Number of Ticks in the y-direction This is set by the gui programmatically
  283. self.z = 1
  284. self.data = None # Data to plot
  285. self.levels = None # Levels for colors
  286. self.step4 = False
  287. self.type=0
  288. self.board_config = board.get_board_config(self.board_id)
  289. self.adc_number = self.board_config.get('adc_number')
  290. self.plotList = []
  291. self.scanyAll = []
  292. self.delays = np.zeros(self.adc_number)
  293. # -------[ Create structure ]----------
  294. self.outerLayout = QtGui.QVBoxLayout() # Outermost layout of this window
  295. self.setLayout(self.outerLayout)
  296. self.plotWidget1 = QtGui.QWidget()
  297. self.plotlayout1 = QtGui.QGridLayout()
  298. self.adc_plot_widgets = []
  299. for i in range(self.adc_number):
  300. self.adc_plot_widgets.append(pg.PlotWidget(title="ADC {}".format(i+1)))
  301. for i,item in enumerate(self.adc_plot_widgets):
  302. self.plotlayout1.addWidget(item, i//(self.adc_number//2), i%(self.adc_number//2))
  303. self.plotWidget1.setLayout(self.plotlayout1)
  304. self.plotWidget2 = QtGui.QWidget()
  305. self.plotlayout2 = QtGui.QGridLayout() # Main Layout to hold the most elements in this window
  306. self.all_plot_widget = pg.PlotWidget(title="over Time")
  307. self.plotlayout2.addWidget(self.all_plot_widget, 0, 0)
  308. self.plotWidget2.setLayout(self.plotlayout2)
  309. self.layout = QtGui.QGridLayout() # Main Layout to hold the most elements in this window
  310. lineindex = 0
  311. self.adccb = []
  312. for adc in range(self.adc_number):
  313. self.adccb.append(self.createCheckbox('ADC{}'.format(adc+1), checked=True, connect=self.plot, color=colours[adc]))
  314. self.layout.addWidget(self.adccb[adc],lineindex,adc)
  315. lineindex +=1
  316. self.layout.addWidget(self.createLabel('Plot Type:'), lineindex,0)
  317. self.plotSelect = QtGui.QComboBox(self)
  318. self.plotSelect.addItem("default") #0
  319. self.plotSelect.addItem("timecorreted") #1
  320. self.plotSelect.currentIndexChanged.connect(self.changePlotType)
  321. self.layout.addWidget(self.plotSelect, lineindex, 1)
  322. self.showError=self.createCheckbox('show Error', connect=self.plot)
  323. self.layout.addWidget(self.showError, lineindex,2)
  324. self.useCalib=self.createCheckbox('use Calib', connect=self.plot)
  325. self.layout.addWidget(self.useCalib, lineindex,3)
  326. self.showADC=self.createCheckbox('show ADCs', connect=self.plot)
  327. self.layout.addWidget(self.showADC, lineindex,4)
  328. self.updateCalib = self.createButton('Update Calibration', connect=self.onUpdateCalibration)
  329. self.layout.addWidget(self.updateCalib, lineindex, 5)
  330. self.correlationTest = self.createButton('Correlation Test', connect=self.onCorrelation)
  331. self.layout.addWidget(self.correlationTest, lineindex, 6)
  332. lineindex += 1
  333. self.multiBunchSelector = self.createSpinbox(0,184, start_value=0, interval=1, connect=self.plot)
  334. self.multiBunchSelectorLabel = self.createLabel('Bunch Selection:')
  335. self.layout.addWidget(self.multiBunchSelectorLabel, lineindex, 0)
  336. self.layout.addWidget(self.multiBunchSelector, lineindex, 1)
  337. self.multiBunchSelector.hide()
  338. self.multiBunchSelectorLabel.hide()
  339. lineindex += 1
  340. self.fitSin=self.createCheckbox('plot Fit', connect=self.plot)
  341. self.layout.addWidget(self.fitSin, lineindex,0)
  342. self.fitSelect = QtGui.QComboBox(self)
  343. self.fitSelect.addItem("Linear") #0
  344. self.fitSelect.addItem("Gauss") #1
  345. self.fitSelect.addItem("Exponential mod Gauss") #2
  346. self.fitSelect.addItem("Exponential mod Gauss V2") #3
  347. self.fitSelect.addItem("skew Gauss") #4
  348. self.fitSelect.addItem("Sinus") #5
  349. self.fitSelect.currentIndexChanged.connect(self.plot)
  350. self.layout.addWidget(self.fitSelect, lineindex, 1)
  351. self.fitoffset = self.createSpinbox(-1000,1100, start_value=-1, interval=1, connect=self.plot)
  352. self.layout.addWidget(self.fitoffset, lineindex,2)
  353. self.fitInfoLable = self.createLabel()
  354. self.layout.addWidget(self.fitInfoLable, lineindex, 4)
  355. self.invertFit=self.createCheckbox('invert Fit', connect=self.plot)
  356. self.layout.addWidget(self.invertFit, lineindex, 3)
  357. lineindex += 1
  358. self.outerLayout.addWidget(self.plotWidget1)
  359. self.outerLayout.addWidget(self.plotWidget2)
  360. self.plotWidget2.hide()
  361. self.outerLayout.addLayout(self.layout)
  362. self.setWindowTitle("Scan Results")
  363. Elements.addButton(['timescan', 'acquire_{}'.format(self.board_id)], [
  364. self.updateCalib,
  365. self.correlationTest,
  366. self.useCalib,
  367. self.showError,
  368. self.showADC,
  369. self.fitSin
  370. ])
  371. # Initially show the plot
  372. self.line_plot()
  373. self.board_config.observe(self, self.setADCdelays, 'chip_delay')
  374. self.board_config.observe(self, self.setADCdelays, 'delay_330_th')
  375. self.board_config.observe(self, self.setADCdelays, 'delay_25_th')
  376. self.board_config.observe(self, self.setADCdelays, 'delay_25_th_2')
  377. def setADCdelays(self, value):
  378. #print('set ADC Delays')
  379. self.delays = np.zeros(self.adc_number)
  380. id = 'None'
  381. if self.useCalib.isChecked():
  382. id = 'current'
  383. for i in range(self.adc_number):
  384. 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"), id=id)
  385. self.delays[i] = value
  386. self.plotADCPositions()
  387. def setPlotParams(self, c_min, c_max, c25_min, c25_max, f_min, f_max, step4):
  388. self.xrange = (c_min, c_max)
  389. self.zrange = (c25_min, c25_max)
  390. self.yrange = (f_min, f_max)
  391. self.step4 = step4
  392. @pyqtSlot(object)
  393. def new_data(self, timeScan):
  394. #while self.block:
  395. # pass
  396. self.block = True
  397. self.timeScan = timeScan
  398. if self.timeScan.multibunch:
  399. self.multiBunchSelector.show()
  400. self.multiBunchSelectorLabel.show()
  401. else:
  402. self.multiBunchSelector.hide()
  403. self.multiBunchSelectorLabel.hide()
  404. self.plot(True)
  405. self.block = False
  406. def changePlotType(self, type):
  407. self.type=type
  408. if type == 0:
  409. self.plotWidget2.hide()
  410. self.plotWidget1.show()
  411. self.plot()
  412. else:
  413. self.plotWidget1.hide()
  414. self.plotWidget2.show()
  415. self.plot()
  416. def onUpdateCalibration(self):
  417. if self.timeScan is not None:
  418. calibrationUpdater = UpdateCalibrationWidget.addUpdateCalibrationWidget()
  419. calibrationUpdater.openWith(self.timeScan, bunch=self.multiBunchSelector.value())
  420. def onCorrelation(self):
  421. if self.timeScan is not None:
  422. w = CorrelationWidget.addCorrelationWidget()
  423. w.updateTimeScan(self.timeScan)
  424. ##################################################################################
  425. def line_plot_axis_strings(self, values, scale, spacing):
  426. """
  427. Plot to format the strings for the line plot
  428. This is used to override the default tickStrings method of pyqtgraph.AxisItem
  429. :param values: See pyqtgraph.AxisItem.tickStrings
  430. :param scale: See pyqtgraph.AxisItem.tickStrings
  431. :param spacing: See pyqtgraph.AxisItem.tickStrings
  432. :return: See pyqtgraph.AxisItem.tickStrings
  433. """
  434. #print(values)
  435. mult = 1
  436. if self.step4:
  437. mult = 4
  438. coarses = [self.xrange[0] + i//(self.x) for i in values]
  439. c25 = [self.zrange[0] + (i//(self.y))%(self.z) for i in values]
  440. fines = [self.yrange[0] + i%(self.y) for i in values]
  441. if board.get_board_config(self.board_id).is_KAPTURE2():
  442. return [str(int(c))+"\n"+str(int(c25*mult))+"\n"+str(int(f)) for c, c25, f in zip(coarses, c25, fines)]
  443. else:
  444. return [str(int(c))+"\n"+str(int(f)) for c, f in zip(coarses, fines)]
  445. ##################################################################################
  446. def spacing(self, minVal, maxVal, size):
  447. """
  448. Calculate spacing between ticks
  449. This is used to override the default tickSpacing method of pyqtgraph.AxisItem
  450. :param minVal: See pyqtgraph.AxisItem.tickSpacing
  451. :param maxVal: See pyqtgraph.AxisItem.tickSpacing
  452. :param size: See pyqtgraph.AxisItem.tickSpacing
  453. :return: See pyqtgraph.AxisItem.tickSpacing
  454. """
  455. if maxVal - minVal < 10.:
  456. return [(1, 0),]
  457. else:
  458. return [(round((maxVal-minVal)/10.), 0),]
  459. ##################################################################################
  460. def y_axis_strings(self, values, scale, spacing):
  461. """
  462. Sets the strings for the y axis
  463. :param values:
  464. :param scale:
  465. :param spacing:
  466. :return:
  467. """
  468. if np.mean(values) > 3:
  469. return [str(int(v)) for v in values]
  470. return [str(v) for v in values]
  471. ##################################################################################
  472. def line_plot(self):
  473. """
  474. Initialise the Line Plot
  475. :return: -
  476. """
  477. self.plot_type = "line"
  478. for item in self.adc_plot_widgets:
  479. item.enableAutoRange()
  480. item.plotItem.setLabel("left", "Intensity")
  481. item.plotItem.setLabel("bottom", "Coarse over Fine")
  482. bax = item.plotItem.getAxis('bottom')
  483. lax = item.plotItem.getAxis('left')
  484. bax.setTickSpacing()
  485. bax.tickSpacing = self.spacing
  486. bax.tickStrings = self.line_plot_axis_strings
  487. lax.setTickSpacing()
  488. def setAxis(axis, lable, unit="", setSpace=False):
  489. labelStyle = {'color': '#000', 'font-size': '14pt'}
  490. axis.setLabel(lable, units=unit, **labelStyle)
  491. font=QtGui.QFont()
  492. font.setPixelSize(15)
  493. axis.tickFont = font
  494. axis.setStyle(tickTextOffset = 20)
  495. if unit != "":
  496. axis.enableAutoSIPrefix()
  497. if setSpace:
  498. axis.setWidth(int(80))
  499. setAxis(self.all_plot_widget.plotItem.getAxis('bottom'), 't', 's')
  500. setAxis(self.all_plot_widget.plotItem.getAxis('left'), 'ADC counts', '', True)
  501. ##################################################################################
  502. def plot(self, nonblock=False):
  503. """
  504. Plot Data
  505. :return: -
  506. """
  507. """
  508. if self.block:
  509. if nonblock == False:
  510. return
  511. else:
  512. self.block = True
  513. """
  514. try:
  515. #print('plot')
  516. if self.timeScan is None:
  517. return
  518. if self.type == 0:
  519. self.z = 1
  520. if board.get_board_config(self.board_id).is_KAPTURE2():
  521. self.z = (self.zrange[1]-self.zrange[0]+1)
  522. if self.step4:
  523. self.z = self.z//4+1
  524. self.y = (self.yrange[1]-self.yrange[0]+1)
  525. self.x = self.z*self.y
  526. for i, item in enumerate(self.adc_plot_widgets):
  527. item.plotItem.clear()
  528. #item.plotItem.plot(np.array(self.timeScan.scanData[i]).T[0])
  529. scanx, scany, scane = self.timeScan.getScanOverDelay(i, bunch=self.multiBunchSelector.value())
  530. item.plotItem.plot(scany)
  531. else:
  532. self.all_plot_widget.plotItem.clear()
  533. #if self.useCalib.isChecked():
  534. # self.calibrationFile = h5py.File(config.config_path('calibration.hdf'), 'r')
  535. dt = []
  536. self.scanyAll = []
  537. text = ""
  538. for i in range(self.adc_number):
  539. if self.adccb[i].isChecked():
  540. scanx, scany, scane = self.timeScan.getScanOverTime(i, calibrateX=self.useCalib.isChecked(), calibrateY=self.useCalib.isChecked(), bunch=self.multiBunchSelector.value())
  541. #scanx, scany = self.calibrate(self.data[i], i)
  542. self.scanyAll.append(scany)
  543. self.all_plot_widget.plotItem.plot(scanx, scany, pen=None, symbolPen=pg.mkPen(colours[i]), symbolSize=2, pxMode=True, symbolBrush=pg.mkBrush(colours[i]), downsample=200)
  544. if self.showError.isChecked():
  545. self.all_plot_widget.plotItem.addItem(pg.ErrorBarItem(x=scanx, y=scany, height=scane, pen=pg.mkPen(coloursTrans[i], width=2), autoDownsample=True, clipToView=True ))
  546. if self.fitSin.isChecked():
  547. # display fit
  548. try:
  549. type = self.fitSelect.currentIndex()
  550. popt, perr, fitFun, pcov, label, x = self.doFit(scanx, scany, type)
  551. fitx = np.linspace(np.min(scanx), np.max(scanx), 100000)
  552. fity = fitFun(fitx, *popt)
  553. self.plot_widget.plotItem.plot(fitx, fity, pen=pg.mkPen(colours[i]), downsample=200)
  554. if type == SINUS:
  555. dt.append(popt[3]/(2*np.pi)/popt[1]*1e12)
  556. elif type in [GAUSS, EGAUSS, SKEW, EGAUSSB, GAUSSB]:
  557. try:
  558. dt.append(fitx[np.where(fity==np.min(fity))][0]*1e12)
  559. except:
  560. pass
  561. except:
  562. pass
  563. if self.fitSin.isChecked():
  564. if type in [SINUS, GAUSS, EGAUSS, SKEW, EGAUSSB, GAUSSB]:
  565. text += 'delta T '
  566. for i in range(len(dt)):
  567. text += '| {:.3f}ps '.format(dt[0]-dt[i])
  568. self.fitInfoLable.setText(text)
  569. self.plotADCPositions()
  570. #if self.useCalib.isChecked():
  571. # self.calibrationFile.close()
  572. # ---[ Show this window and set focus to it ]------
  573. self.parent().show()
  574. self.show()
  575. except:
  576. pass
  577. self.block = False
  578. #self.setFocus()
  579. def plotADCPositions(self):
  580. if self.type != 1:
  581. return
  582. if not self.showADC.isChecked():
  583. return
  584. #print('plot delays')
  585. if self.scanyAll == []:
  586. self.scanyAll.extend([0,1])
  587. i=1
  588. font = QtGui.QFont()
  589. font.setPixelSize(14)
  590. if self.plotList != []:
  591. for item in self.plotList:
  592. self.all_plot_widget.plotItem.removeItem(item)
  593. self.plotList = []
  594. for x in self.delays:
  595. if self.adccb[i-1].isChecked():
  596. self.plotList.append(self.all_plot_widget.plotItem.plot([x,x], [np.min(self.scanyAll)-10, np.max(self.scanyAll)+20], pen=pg.mkPen(colours[0]), downsample=200))
  597. text = pg.TextItem(str(i), anchor=(0.5,1), color=colours[i-1])
  598. text.setFont(font)
  599. text.setPos(x,np.max(self.scanyAll)+24)
  600. self.all_plot_widget.addItem(text)
  601. self.plotList.append(text)
  602. i += 1
  603. def doFit(self, x,y, type, p0=None):
  604. def linear(x,a,b):
  605. return a + b*x
  606. def gauss(x, sigma, mu, A, b):
  607. return A*np.exp(-0.5*((x-mu)/sigma)**2) + b
  608. def expgauss(x, s, m, a ,l, b):
  609. return a*l/2*np.exp(l/2*(2*m + l*s**2 - 2*x)) * erfc((m +l*s**2 -x)/(np.sqrt(2)*s)) + b
  610. def expgauss2(x, s, m, a, t, b):
  611. return a*s/t*np.sqrt(np.pi/2) * np.exp(0.5 * (s/t)**2 - (x-m)/t) * erfc(1/np.sqrt(2)*(s/t - (x-m)/s)) + b
  612. def sinus(x,a,b,c,d):
  613. return a*np.sin(b*x*(2*np.pi)+d)+c
  614. def skewnorm(x, s, m, a, l, b):
  615. def p(x):
  616. return 1/np.sqrt(2*np.pi) * np.exp(- x**2/2)
  617. def g(x):
  618. return 0.5*(1+erf(x/np.sqrt(2)))
  619. return a*2/s*p((x-m)/s)*g(l*(x-m)/s) +b
  620. if self.invertFit.isChecked():
  621. startx = x[np.where(y==np.min(y))]
  622. else:
  623. startx = x[np.where(y==np.max(y))]
  624. y = y[np.argsort(x)]
  625. x = x[np.argsort(x)]
  626. if type == LINEAR:
  627. fitFun = linear
  628. label = ['a' , 'b']
  629. elif type == GAUSS:
  630. fitFun = gauss
  631. p0 = (90e-12, startx, 500, 2000)
  632. label = ['sigma', ' mu ', ' A ', ' b ']
  633. if self.invertFit.isChecked():
  634. p0 = (90e-12, startx, -500, 2000)
  635. end = np.argmax(y)+self.fitoffset.value()
  636. x = x[:end]
  637. y = y[:end]
  638. elif type == EGAUSS:
  639. fitFun = expgauss
  640. p0 = (23e-12, startx, 7e-8, 0.02e12, 2040)
  641. if self.invertFit.isChecked():
  642. p0 = (23e-12, startx, -7e-8, 0.02e12, 2040)
  643. label = [' s ', ' m ', ' a ', ' l ', ' b ']
  644. elif type == EGAUSSB:
  645. fitFun = expgauss2
  646. p0 = (22e-12, startx, 1200, 70e-12, 2040)
  647. if self.invertFit.isChecked():
  648. p0 = (22e-12, startx, -1200, 70e-12, 2040)
  649. end = self.fitoffset.value()
  650. x = x[:end]
  651. y = y[:end]
  652. label = [' s ', ' m ', ' a ', ' l ', ' b ']
  653. elif type == SKEW:
  654. fitFun = skewnorm
  655. end = self.fitoffset.value()
  656. x = x[:end]
  657. y = y[:end]
  658. p0 = (80e-12, startx, 6e-8, 3, 2040) # 220e-12
  659. label = [' s ', ' m ', ' a ', ' l ', ' b ']
  660. if self.invertFit.isChecked():
  661. p0 = (80e-12, startx, -6e-8, 3, 2040) # 220e-12
  662. elif type == SINUS:
  663. fitFun = sinus
  664. if p0 == None:
  665. p0 = (-700, 500e6, 2048, 0.5)
  666. label = [' A ', ' f ', ' b ', ' phi']
  667. else:
  668. print('Fit type unknown ', type)
  669. return 0,0, lambda x: x , 0
  670. if p0 is not None:
  671. popt, pcov = curve_fit(fitFun, x, y, p0=p0)
  672. else:
  673. popt, pcov = curve_fit(fitFun, x, y)
  674. #popt = p0
  675. perr = np.sqrt(np.absolute(np.diag(pcov)))
  676. #print(popt)
  677. return popt, perr, fitFun, pcov, label, x
  678. ##################################################################################
  679. def closeEvent(self, event):
  680. """
  681. Event handler for closing this window
  682. """
  683. self.board_config.unobserve(self, 'chip_delay')
  684. self.board_config.unobserve(self, 'delay_330_th')
  685. self.board_config.unobserve(self, 'delay_25_th')
  686. self.board_config.unobserve(self, 'delay_25_th_2')
  687. global __timing_plot_widget_id__
  688. __timing_plot_widget_id__ = {}
  689. global __timing_plot_widget__
  690. __timing_plot_widget__ = None
  691. del self.par.widgets[self.id]
  692. # d8888 888 888 d8b
  693. # d88888 888 888 Y8P
  694. # d88P888 888 888
  695. # d88P 888 888 888 888888 .d88b. 88888b.d88b. 8888b. 888888 888 .d88b. 88888b.
  696. # d88P 888 888 888 888 d88""88b 888 "888 "88b "88b 888 888 d88""88b 888 "88b
  697. # d88P 888 888 888 888 888 888 888 888 888 .d888888 888 888 888 888 888 888
  698. # d8888888888 Y88b 888 Y88b. Y88..88P 888 888 888 888 888 Y88b. 888 Y88..88P 888 888
  699. # d88P 888 "Y88888 "Y888 "Y88P" 888 888 888 "Y888888 "Y888 888 "Y88P" 888 888
  700. #
  701. #
  702. #
  703. class AutomationThread(QtCore.QObject):
  704. '''Automation Thread class'''
  705. updateSignal = QtCore.pyqtSignal(int)
  706. stopSignal = QtCore.pyqtSignal()
  707. startScan = QtCore.pyqtSignal()
  708. poststartScan = QtCore.pyqtSignal()
  709. running = False
  710. def __init__(self, start, stop, step, board_id):
  711. super(AutomationThread, self).__init__()
  712. self.start = start
  713. self.stop = stop
  714. self.step = step
  715. self.board_id = board_id
  716. def scan(self):
  717. self.running = True
  718. for v in range(self.start, self.stop+self.step, self.step):
  719. self.updateSignal.emit(v)
  720. sleep(0.5)
  721. print('startScan')
  722. self.startScan.emit()
  723. while not board.get_board_status(self.board_id).time_scan:
  724. #wait for Scan to start
  725. sleep(0.05)
  726. if not self.running:
  727. self.stopSignal.emit()
  728. return
  729. self.poststartScan.emit()
  730. while board.get_board_status(self.board_id).time_scan:
  731. #wait for Scan to stop
  732. sleep(0.05)
  733. if not self.running:
  734. self.stopSignal.emit()
  735. return
  736. if not self.running:
  737. self.stopSignal.emit()
  738. return
  739. self.running = False
  740. self.stopSignal.emit()
  741. from ..extensions import deltaPower
  742. class Automation(kcgw.KCGWidgets):
  743. def __init__(self, layout, startScan, info, abortScan):
  744. super(Automation, self).__init__()
  745. self.layout = layout
  746. self.startScan = startScan
  747. self.abortScan = abortScan
  748. self.info = info
  749. self.outdir = os.path.join(storage.storage.save_location, storage.storage.subdirname, 'CalibrationScan')
  750. self.running = False
  751. self.power = None #deltaPower.DeltaPower("192.1.1.1")
  752. lineindex = 0
  753. self.layout.addWidget(self.createLabel("Automated Voltage Scan"), lineindex, 0,1,3)
  754. lineindex +=1
  755. self.layout.addWidget(self.createLabel("Power Supply IP"), lineindex, 0)
  756. self.input = self.createInput('10.1.0.101')
  757. self.layout.addWidget(self.input, lineindex, 1,1,2)
  758. self.buttonConnect = self.createButton('connect', connect=self.connect)
  759. self.layout.addWidget(self.buttonConnect, lineindex, 3)
  760. lineindex += 1
  761. self.layout.addWidget(self.createLabel("Spannung (mV)"), lineindex, 0)
  762. self.vin = self.createSpinbox(0,1000, start_value=0)
  763. self.layout.addWidget(self.vin, lineindex, 1)
  764. self.buttonSetV = self.createButton('set', connect=lambda: self.setV(self.vin.value()))
  765. self.layout.addWidget(self.buttonSetV, lineindex, 2)
  766. lineindex += 1
  767. self.layout.addWidget(self.createLabel("Start"), lineindex, 1)
  768. self.layout.addWidget(self.createLabel("Stop"), lineindex, 2)
  769. self.layout.addWidget(self.createLabel("Schritt"), lineindex, 3)
  770. lineindex += 1
  771. self.layout.addWidget(self.createLabel("Spannung (mV)"), lineindex, 0)
  772. self.vmin = self.createSpinbox(0,1000, start_value=0)
  773. self.vmax = self.createSpinbox(0,1000, start_value=800)
  774. self.vstep = self.createSpinbox(0,500, start_value=20)
  775. self.layout.addWidget(self.vmin, lineindex, 1)
  776. self.layout.addWidget(self.vmax, lineindex, 2)
  777. self.layout.addWidget(self.vstep, lineindex, 3)
  778. lineindex += 1
  779. self.button = self.createButton('start', connect=self.start)
  780. self.layout.addWidget(self.button, lineindex, 0)
  781. Elements.addButton(['timescan','acquire_0', 'automation'], [self.button, self.buttonConnect, self.buttonSetV])
  782. Elements.addButton(['automation'], [self.input, self.vin, self.vmin, self.vmax, self.vstep])
  783. lineindex += 1
  784. self.progressbar = QtGui.QProgressBar()
  785. self.layout.addWidget(self.progressbar, lineindex,0,1,4)
  786. self.progressbar.setRange(0,1000)
  787. lineindex += 1
  788. self.tst = None
  789. def connect(self):
  790. try:
  791. self.power = deltaPower.DeltaPower(str(self.input.text()))
  792. except Exception as e:
  793. logging.error('Not connected to Powersupply - ' + str(e))
  794. self.power = None
  795. def setV(self, value):
  796. if self.power is not None:
  797. self.power.write_Voltage(value/1000.0)
  798. else:
  799. logging.error('no Powersupply')
  800. def start(self):
  801. self.thread = storage.get_board_specific_storage(available_boards[0]).setdefault("AutoScanThread", storage.ThreadStorage())
  802. if self.thread.running:
  803. logging.info("Time scan already running")
  804. self.tst.running = False
  805. return
  806. start = self.vmin.value()
  807. stop = self.vmax.value()
  808. step = self.vstep.value()
  809. fileinfo = os.path.join(self.outdir, 'scan.info')
  810. f = open(fileinfo, 'a')
  811. f.write('##########################\n')
  812. f.write('#Automated Voltage Scan\n')
  813. f.write('#Range: {:4d} - {:4d}\n'.format(start,stop))
  814. f.write('#Step: {:4d}\n'.format(step))
  815. f.write('\n')
  816. f.close()
  817. self.tst = AutomationThread(start, stop, step, available_boards[0])
  818. self.thread.register(self.tst)
  819. self.thread.connect('updateSignal', self.update)
  820. self.thread.connect('stopSignal', self.stop)
  821. self.thread.connect('startScan', self.startScan)
  822. self.thread.connect('poststartScan', self.reactivateButton)
  823. self.progressbar.setRange(start, stop+step)
  824. self.thread.start('scan')
  825. self.scaning = True
  826. self.button.setText('stop')
  827. Elements.setEnabled('automation', False, exclude=[self.button])
  828. Elements.setEnabled('timescan', False)
  829. def stop(self):
  830. if board.get_board_status(available_boards[0]).time_scan:
  831. self.abortScan()
  832. while board.get_board_status(available_boards[0]).time_scan:
  833. sleep(0.05)
  834. self.thread.stop()
  835. self.scaning = False
  836. print('Automation Stop')
  837. self.progressbar.setValue(self.vmax.value()+self.vstep.value())
  838. self.button.setText('start')
  839. Elements.setEnabled('automation', True)
  840. Elements.setEnabled('timescan', True)
  841. fileinfo = os.path.join(self.outdir, 'scan.info')
  842. f = open(fileinfo, 'a')
  843. f.write('#End\n')
  844. f.write('##########################\n')
  845. f.write('\n')
  846. f.close()
  847. pass
  848. def update(self, value):
  849. self.setV(value)
  850. self.progressbar.setValue(value)
  851. self.info.setText("Auto: {:4d} mV".format(value))
  852. print('Automation update')
  853. pass
  854. def reactivateButton(self):
  855. self.button.setEnabled(True)
  856. # 88888888888 d8b .d8888b. 888 888 d8b 888 888
  857. # 888 Y8P d88P Y88b 888 o 888 Y8P 888 888
  858. # 888 Y88b. 888 d8b 888 888 888
  859. # 888 888 88888b.d88b. .d88b. "Y888b. .d8888b 8888b. 88888b. 888 d888b 888 888 .d88888 .d88b. .d88b. 888888
  860. # 888 888 888 "888 "88b d8P Y8b "Y88b. d88P" "88b 888 "88b 888d88888b888 888 d88" 888 d88P"88b d8P Y8b 888
  861. # 888 888 888 888 888 88888888 "888 888 .d888888 888 888 88888P Y88888 888 888 888 888 888 88888888 888
  862. # 888 888 888 888 888 Y8b. Y88b d88P Y88b. 888 888 888 888 8888P Y8888 888 Y88b 888 Y88b 888 Y8b. Y88b.
  863. # 888 888 888 888 888 "Y8888 "Y8888P" "Y8888P "Y888888 888 888 888P Y888 888 "Y88888 "Y88888 "Y8888 "Y888
  864. # 888
  865. # Y8b d88P
  866. # "Y88P"
  867. class TimeScanWidget(kcgw.KCGWidgets):
  868. def __init__(self, unique_id, parent):
  869. super(TimeScanWidget, self).__init__()
  870. self.scaning = False
  871. self.id = unique_id
  872. self.par = parent
  873. self.scanNumber = 0
  874. #self.layout = QtGui.QHBoxLayout()
  875. self.board_id = available_boards[0]
  876. self.board_config = board.get_board_config(self.board_id)
  877. self.layout = QtGui.QGridLayout()
  878. self.outerLayout = QtGui.QVBoxLayout()
  879. self.outerLayout.addLayout(self.layout)
  880. self.setLayout(self.outerLayout)
  881. lineindex = 0
  882. if self.board_config.is_KAPTURE2():
  883. #KAPTURE 2#########################################
  884. self.layout.addWidget(self.createLabel("330 ps Delay"), lineindex, 0)
  885. self.delaythmin = self.createSpinbox(0,6, start_value=0)
  886. self.delaythmax = self.createSpinbox(0,12, start_value=6)
  887. self.layout.addWidget(self.delaythmin, lineindex, 1)
  888. self.layout.addWidget(self.delaythmax, lineindex, 2)
  889. lineindex += 1
  890. self.layout.addWidget(self.createLabel("25 ps Delay"), lineindex, 0)
  891. self.delay25min = self.createSpinbox(0,23, start_value=0)
  892. self.delay25max = self.createSpinbox(0,23, start_value=12)
  893. self.layout.addWidget(self.delay25min, lineindex, 1)
  894. self.layout.addWidget(self.delay25max, lineindex, 2)
  895. lineindex += 1
  896. self.stepSwitcher = self.createSwitch(startRight=True)
  897. self.layout.addWidget(self.createLabel("25ps Step 1"), lineindex, 0)
  898. self.layout.addWidget(self.stepSwitcher, lineindex, 1)
  899. self.layout.addWidget(self.createLabel("25ps Step 4"), lineindex, 2)
  900. lineindex += 1
  901. Elements.addButton(['timescan'], [
  902. self.delaythmin,
  903. self.delaythmax,
  904. self.delay25max,
  905. self.delay25min,
  906. self.stepSwitcher
  907. ])
  908. else:
  909. #KAPTURE 1#########################################
  910. self.layout.addWidget(self.createLabel("ADC to T/H Delay"), lineindex, 0)
  911. self.delayADCTH = self.createSpinbox(0,15, start_value=self.board_config.get('th_to_adc_cycles'), connect=lambda x: self.board_config.update('th_to_adc_cycles', x))
  912. self.layout.addWidget(self.delayADCTH, lineindex, 1)
  913. lineindex += 1
  914. line = QtGui.QFrame()
  915. line.setFrameStyle(QtGui.QFrame.HLine)
  916. self.layout.addWidget(line, lineindex, 0, 1, 10)
  917. lineindex += 1
  918. self.layout.addWidget(self.createLabel("T/H Delay"), lineindex, 0)
  919. self.delaythmin = self.createSpinbox(0,15, start_value=0)
  920. self.delaythmax = self.createSpinbox(0,15, start_value=15)
  921. self.layout.addWidget(self.delaythmin, lineindex, 1)
  922. self.layout.addWidget(self.delaythmax, lineindex, 2)
  923. lineindex += 1
  924. Elements.addButton(['timescan'], [
  925. self.delaythmin,
  926. self.delaythmax,
  927. self.delayADCTH
  928. ])
  929. self.layout.addWidget(self.createLabel("Fine Delay"), lineindex, 0)
  930. self.delayfinemin = self.createSpinbox(0,31, start_value=0)
  931. self.delayfinemax = self.createSpinbox(0,31, start_value=31)
  932. self.layout.addWidget(self.delayfinemin, lineindex, 1)
  933. self.layout.addWidget(self.delayfinemax, lineindex, 2)
  934. lineindex += 1
  935. self.layout.addWidget(self.createLabel("Number of turns"), lineindex, 0)
  936. self.numofturns = self.createSpinbox(0,1e6, start_value=1000)
  937. self.layout.addWidget(self.numofturns, lineindex, 1)
  938. lineindex += 1
  939. self.layout.addWidget(self.createLabel("Turns to skip"), lineindex, 0)
  940. self.numofturnsSkip = self.createSpinbox(0,1e6, start_value=0)
  941. self.layout.addWidget(self.numofturnsSkip, lineindex, 1)
  942. lineindex += 1
  943. self.layout.addWidget(self.createLabel("Identifyer"), lineindex, 0)
  944. self.input = self.createInput()
  945. self.layout.addWidget(self.input, lineindex, 1)
  946. lineindex += 1
  947. self.comboBox = QtGui.QComboBox(self)
  948. self.comboBox.addItem("Mean over Everything", MODE_ALL) #0
  949. self.comboBox.addItem("Use Threshold", MODE_THREASHOLD) #1
  950. #self.comboBox.addItem("Use Bucket Detection - processed after scan", MODE_AUTOBUCKET) #2
  951. #self.comboBox.addItem("Use Bucket Detection and Threshold for live", MODE_AUTOBUCKET_TMP_THRESHOLD) #3
  952. self.comboBox.addItem("Use Bucket", MODE_BUCKET) #4
  953. #self.comboBox.addItem("Use TDS Mode", MOD) #5
  954. self.comboBox.addItem("Use All Buckets", MODE_ALL_BUCKETS) #6
  955. self.layout.addWidget(self.comboBox, lineindex, 0,1,3)
  956. lineindex += 1
  957. self.layout.addWidget(self.createLabel("Threshold / Bucket"), lineindex, 0)
  958. self.threshold = self.createSpinbox(-2000,2000, start_value=15)
  959. self.layout.addWidget(self.threshold, lineindex, 1)
  960. lineindex += 1
  961. Elements.addButton(['timescan'], [
  962. self.delayfinemin,
  963. self.delayfinemax,
  964. self.numofturns,
  965. self.numofturnsSkip,
  966. self.input,
  967. self.comboBox,
  968. self.threshold
  969. ])
  970. self.layout.addWidget(self.createLabel("Fast Mode"), lineindex, 0)
  971. self.fastModeSelector = self.createSwitch('Fast Mode', connect=self.setFastMode)
  972. self.fastModeSelector.setState(False)
  973. self.layout.addWidget(self.fastModeSelector, lineindex, 1)
  974. lineindex +=1
  975. if self.board_config.is_KAPTURE2():
  976. self.layout.addWidget(self.createLabel("Calibration Scan"), lineindex, 0)
  977. self.calibSelector = self.createSwitch('Calibration Scan')
  978. self.calibSelector.setState(False)
  979. self.layout.addWidget(self.calibSelector, lineindex, 1)
  980. lineindex +=1
  981. self.button = self.createButton('start', connect=self.startScan)
  982. self.layout.addWidget(self.button, lineindex, 1,1,2)
  983. Elements.addButton(['timescan','acquire_0'], self.button)
  984. self.saverawCB = self.createCheckbox('save Raw', checked=False)
  985. self.layout.addWidget(self.saverawCB, lineindex, 0)
  986. lineindex += 1
  987. self.labelBucket = self.createLabel("")
  988. self.layout.addWidget(self.labelBucket, lineindex, 0,1,3)
  989. lineindex += 1
  990. self.progressbar = QtGui.QProgressBar()
  991. self.layout.addWidget(self.progressbar, lineindex,0,1,3)
  992. self.progressbar.setRange(0,1000)
  993. lineindex += 1
  994. line = QtGui.QFrame()
  995. line.setFrameStyle(QtGui.QFrame.HLine)
  996. self.layout.addWidget(line, lineindex, 0, 1, 3)
  997. lineindex += 1
  998. ###########################################################
  999. ### Automation
  1000. #self.automationLayout = QtGui.QGridLayout()
  1001. #self.outerLayout.addLayout(self.automationLayout)
  1002. #self.auto = Automation(self.automationLayout, self.startScan, self.input, self.abort)
  1003. ###########################################################
  1004. self.outerLayout.addStretch(1)
  1005. self.adjustSize()
  1006. #self.layout.addStretch(1)
  1007. self.setWindowTitle("Time Scan Widget")
  1008. self.openPlotWidget()
  1009. self.tst = None
  1010. def setFastMode(self):
  1011. if self.fastModeSelector.state:
  1012. self.delaythmin.setValue(0)
  1013. self.delaythmax.setValue(6)
  1014. self.delay25min.setValue(0)
  1015. self.delay25max.setValue(12)
  1016. self.delayfinemax.setValue(0)
  1017. self.delayfinemin.setValue(0)
  1018. self.threshold.setValue(15)
  1019. self.comboBox.setCurrentIndex(1)
  1020. self.stepSwitcher.setState(False)
  1021. self.calibSelector.setState(False)
  1022. self.stepSwitcher.setEnabled(False)
  1023. self.calibSelector.setEnabled(False)
  1024. self.delayfinemin.setEnabled(False)
  1025. self.delayfinemax.setEnabled(False)
  1026. self.saverawCB.setChecked(False)
  1027. else:
  1028. self.delaythmin.setValue(0)
  1029. self.delaythmax.setValue(6)
  1030. self.delay25min.setValue(0)
  1031. self.delay25max.setValue(12)
  1032. self.delayfinemax.setValue(32)
  1033. self.delayfinemin.setValue(0)
  1034. self.threshold.setValue(3)
  1035. self.comboBox.setCurrentIndex(3)
  1036. self.stepSwitcher.setState(True)
  1037. self.stepSwitcher.setEnabled(True)
  1038. self.calibSelector.setEnabled(True)
  1039. self.delayfinemin.setEnabled(True)
  1040. self.delayfinemax.setEnabled(True)
  1041. #self.saverawCB.setChecked(True)
  1042. def openPlotWidget(self):
  1043. global __timing_plot_widget_id__
  1044. global __timing_plot_widget__
  1045. if __timing_plot_widget__ == None:
  1046. nid = kcgw.idg.genid()
  1047. __timing_plot_widget_id__[self.board_id] = nid
  1048. self.plotWidget = ScanPlotWidget(nid, self.board_id, global_objects.get_global('area'))
  1049. __timing_plot_widget__ = self.plotWidget
  1050. global_objects.get_global('area').newWidget(self.plotWidget, "Timing result", nid, widget_type=5)
  1051. def startScan(self):
  1052. if not self.scaning:
  1053. Elements.setEnabled('acquire_{}'.format(self.board_id), False, exclude=[self.button])
  1054. Elements.setEnabled("acquireTrigger_{}".format(self.board_id), False)
  1055. if __timing_plot_widget__ == None:
  1056. __timing_plot_widget__.showError.setChecked(False)
  1057. __timing_plot_widget__.useCalib.setChecked(False)
  1058. __timing_plot_widget__.fitSin.setChecked(False)
  1059. __timing_plot_widget__.showADC.setChecked(False)
  1060. outdir = os.path.join(storage.storage.save_location, storage.storage.subdirname, 'TimeScan')
  1061. if not os.path.isdir(outdir):
  1062. bif._bif_update_working_dir()
  1063. os.makedirs(outdir)
  1064. self.scanNumber = 0
  1065. filelist = np.sort(os.listdir(outdir))
  1066. for file in filelist:
  1067. if '.scan' in file:
  1068. self.scanNumber += 1
  1069. saveraw = self.saverawCB.isChecked()
  1070. #print(saveraw)
  1071. self.board_config.update('turns_observe', self.numofturns.value())
  1072. self.board_config.update('turns_skip', self.numofturnsSkip.value())
  1073. if self.board_config.is_KAPTURE2():
  1074. self.start(self.delaythmin.value(), self.delaythmax.value(), self.delayfinemin.value(), self.delayfinemax.value(),
  1075. self.input.text(), outdir, self.threshold.value(), saveraw,
  1076. c25_min=self.delay25min.value(), c25_max=self.delay25max.value(), step4=self.stepSwitcher.state,
  1077. meanMode =self.comboBox.itemData(self.comboBox.currentIndex()), fastMode=self.fastModeSelector.state, calibScan=self.calibSelector.state)
  1078. else:
  1079. self.start(self.delaythmin.value(), self.delaythmax.value(), self.delayfinemin.value(), self.delayfinemax.value(),
  1080. self.input.text(), outdir, self.threshold.value(), saveraw, meanMode =self.comboBox.itemData(self.comboBox.currentIndex()))
  1081. else:
  1082. self.abort()
  1083. #self.stop()
  1084. def start(self, c_min, c_max, f_min, f_max, ident, outdir, threshold, saveraw, c25_min=-1, c25_max=-1, step4=False, meanMode=MODE_ALL, fastMode=False, calibScan=False):
  1085. try:
  1086. self.progressbar.setValue(0)
  1087. board.get_board_status(self.board_id).time_scan = True
  1088. self.openPlotWidget()
  1089. self.plotWidget.setPlotParams(c_min, c_max, c25_min, c25_max, f_min, f_max, step4)
  1090. self.thread = storage.get_board_specific_storage(self.board_id).setdefault("TimeScanThread", storage.ThreadStorage())
  1091. if self.thread.running:
  1092. logging.info("Time scan already running")
  1093. return
  1094. self.tst = ScanThread(c_min, c_max, f_min, f_max, available_boards[0], self.scanNumber, ident, outdir, threshold, saveraw, c25_min, c25_max, step4, meanMode, fastMode, calibScan)
  1095. self.thread.register(self.tst)
  1096. self.thread.connect('pbarSignal', self.update)
  1097. self.thread.connect('stopSignal', self.stop)
  1098. self.thread.connect('plotSignal', self.plot)
  1099. self.thread.start('scan')
  1100. self.scaning = True
  1101. self.button.setText('stop')
  1102. except Exception as e:
  1103. logging.error('Start Calibrationscan: ' + str(e))
  1104. def abort(self):
  1105. if self.tst is not None:
  1106. self.tst.stop = True
  1107. #board.get_board_status(self.board_id).time_scan = False
  1108. def stop(self, timeScan, file):
  1109. self.thread.stop()
  1110. self.openPlotWidget()
  1111. self.plotWidget.new_data(timeScan)
  1112. #self.labelBucket.setText('Signal in Buckets: {}'.format(self.tst.buckets))
  1113. self.scaning = False
  1114. board.get_board_status(self.board_id).time_scan = False
  1115. self.scanNumber +=1
  1116. self.button.setText('start')
  1117. self.progressbar.setValue(1000)
  1118. #self.plotWidget.giveFilename(file)
  1119. Elements.setEnabled('acquire_{}'.format(self.board_id), True)
  1120. Elements.setEnabled("acquireTrigger_{}".format(self.board_id), True)
  1121. print('fine')
  1122. def update(self, timescan, prozent):
  1123. # print(c_step, f_step, data, prozent)
  1124. #print('update')
  1125. self.openPlotWidget()
  1126. self.plotWidget.new_data(timescan)
  1127. self.progressbar.setValue(prozent*1000)
  1128. def plot(self, data):
  1129. #print('plot', len(data_raw))
  1130. #bif._bif_read_and_update_data_from_string(self.board_id, data_raw)
  1131. if live_plot_windows.hasWindows(self.board_id):
  1132. for plotwin in live_plot_windows.getWindows(self.board_id):
  1133. plotwin.plot_live(data=data)
  1134. QtGui.qApp.processEvents()
  1135. def closeEvent(self, event):
  1136. self.abort()
  1137. global __widget_id__
  1138. __widget_id__ = None
  1139. global updateData
  1140. updateData = None
  1141. del self.par.widgets[self.id]
  1142. def addCalibrationWidget():
  1143. global __widget_id__
  1144. if __widget_id__:
  1145. global_objects.get_global('area').widgets[__widget_id__].setFocus()
  1146. else:
  1147. nid = kcgw.idg.genid()
  1148. __widget_id__ = nid
  1149. w = TimeScanWidget(nid, global_objects.get_global('area'))
  1150. global_objects.get_global('area').newWidget(w, "Time Scan Widget", nid, widget_type=4, minSize=True)
  1151. kcgw.register_widget(QtGui.QIcon(config.icon_path("timescan.png")), "Time Scan Widget", addCalibrationWidget, "Ctrl+Shift+T")