TimescanWidget.py 57 KB

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