TimeScan.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. import logging
  2. import time
  3. import os
  4. import csv
  5. import math
  6. import numpy as np
  7. import h5py
  8. import traceback
  9. try:
  10. #Compatibility Python3 and Python 2
  11. from .CalibrationHandle import theCalibration
  12. from .constants import KARA
  13. except:
  14. from CalibrationHandle import theCalibration
  15. from constants import KARA
  16. """
  17. ScanInfo has these fields:
  18. Nr
  19. Info
  20. Threshold
  21. ADC to T/H
  22. T/H
  23. 25ps
  24. fine
  25. Step4
  26. Mode
  27. Fast Mode
  28. Calibration
  29. """
  30. class TimeScan(object):
  31. """
  32. Class to read Timescan files.
  33. ! Be aware: parameter ADC is in range of 0 to 7
  34. """
  35. def __init__(self, filename=None, calibrationFile=""):
  36. """
  37. Initialise the TimeScan
  38. :param filename: string of the rawfile to open. If available it reads automatically the meta information from the Logfile
  39. :param calibrationFile: define the to use calibration. by default it looks for "calibration.hdf" in the same dic as the filename
  40. :return: -
  41. """
  42. self.fileName = filename
  43. self.scanData = None
  44. self.adcNumber = 0
  45. self.scanInfo = None
  46. self.appending = False
  47. self.scanx = None
  48. self.scany = None
  49. self.scane = None
  50. self.calibrateY = False
  51. self.calibrateX = False
  52. self.multibunch = False
  53. self.bunch = 0
  54. self.multibunchData = None
  55. self.multibunchStd = None
  56. self.calibId = "current"
  57. if calibrationFile != "":
  58. self.calibId = theCalibration.openFile(calibrationFile)
  59. else:
  60. if self.fileName is not None:
  61. path = os.path.dirname(os.path.dirname(self.fileName))
  62. self.calibId = theCalibration.openFile(os.path.join(path,'calibration.hdf'))
  63. else:
  64. print('calibrationFile not defined - no calibration possible')
  65. if self.fileName is not None:
  66. if os.path.isfile(self.fileName):
  67. self._loadTimeScan()
  68. self.scanInfo = self._loadScanInfo()
  69. else:
  70. print('File does not exist', self.file)
  71. ###################################################################################################
  72. def getScanInfo(self):
  73. """
  74. :return the logfile entry as a dict
  75. """
  76. return self.scanInfo
  77. def getScanOverTime(self, adc, calibrateX=True, calibrateY=True, force=False, bunch=0):
  78. """
  79. get The Timescan with x-Axis in ps
  80. :param adc: Channel to be returned
  81. :return scanx, scany, scane
  82. """
  83. while self.appending:
  84. pass
  85. if (self.scanx is None) or (self.calibrateX != calibrateX) or (self.calibrateY != calibrateY) or (self.bunch != bunch) or force:
  86. self._prepareScan(calibrateX, calibrateY, bunch, force)
  87. return self.scanx[adc], self.scany[adc], self.scane[adc]
  88. def getScanOverDelay(self, adc, bunch=0):
  89. """
  90. Returns the Scan where the returned x values are the Delays
  91. :return scanx, scany, scane; where scanx is a array of arrays containing [330ps, 25ps, 3ps, 2. 25ps]
  92. """
  93. while self.appending:
  94. pass
  95. dat = np.array(self.scanData[adc])
  96. scanx = np.array([[val[2], val[3], val[4], val[6]] for val in dat])
  97. if self.multibunch:
  98. scany = np.array(self.multibunchData[adc])[:,bunch]
  99. scane = np.array(self.multibunchStd[adc])[:,bunch]
  100. else:
  101. scany = dat.T[0]
  102. scane = dat.T[1]
  103. return scanx, scany, scane
  104. def _loadTimeScan(self):
  105. data = [[],[],[],[], [],[],[],[]]
  106. multibunchData = [[],[],[],[], [],[],[],[]]
  107. multibunchStd = [[],[],[],[], [],[],[],[]]
  108. with open(self.fileName) as f:
  109. reader = csv.reader(f, delimiter=';')
  110. adc = -1
  111. calib = False
  112. for row in reader:
  113. #print(row)
  114. if row == []:
  115. pass
  116. elif '#ADC' in row[0]:
  117. adc += 1
  118. elif '#' in row[0]:
  119. pass
  120. else:
  121. if len(row) < 4:
  122. data[adc].append([float(row[2]), float(0), int(row[0]), int(0), int(row[1]),0,4])
  123. elif len(row) <= 5:
  124. data[adc].append([float(row[3]), float(row[4]), int(row[0]), int(row[1]), int(row[2]),0,4])
  125. else:
  126. if len(row[3]) > 10:
  127. y = np.fromstring(row[3], sep=',')
  128. e = np.fromstring(row[4], sep=',')
  129. multibunchData[adc].append(y)
  130. multibunchStd[adc].append(e)
  131. data[adc].append([y[0], e[0], int(row[0]), int(row[1]), int(row[2]), int(row[5]), int(row[6])])
  132. self.multibunch = True
  133. else:
  134. data[adc].append([float(row[3]), float(row[4]), int(row[0]), int(row[1]), int(row[2]), int(row[5]), int(row[6])])
  135. calib=True
  136. self.scanData = np.array(data[:adc+1])
  137. self.adcNumber = adc+1
  138. if self.multibunch is not None:
  139. self.multibunchData = np.array(multibunchData)
  140. self.multibunchStd = np.array(multibunchStd)
  141. print('adcNumber', self.adcNumber)
  142. def _loadScanInfo(self):
  143. file = os.path.join(os.path.dirname(self.fileName), 'scan.info')
  144. basename = os.path.basename(self.fileName)
  145. with open(file, 'r') as f:
  146. scaninfo = f.read().split('Scan\n')[1:]
  147. for item in scaninfo:
  148. tmp = {}
  149. tmp['File'] = ""
  150. for v in item.split('\n'):
  151. if '#' in v:
  152. continue
  153. t = v.split(':')
  154. if len(t)>1:
  155. if 'T/H' in str(t[0]) and 'ADC' not in str(t[0]):
  156. tmp['T/H'] = np.array(t[1].split('-'), dtype=np.int)
  157. elif 'fine' in str(t[0]):
  158. tmp['fine'] = np.array(t[1].split('-'), dtype=np.int)
  159. elif '25ps' in str(t[0]):
  160. tmp['25ps'] = np.array(t[1].split('-'), dtype=np.int)
  161. else:
  162. tmp[str(t[0])] = t[1].strip(' ')
  163. if tmp['File'] == basename:
  164. return tmp
  165. print('no ScanInfo')
  166. return None
  167. def _prepareScan(self, calibrateX, calibrateY, bunch=0, force=True):
  168. #print('_prepareScan')
  169. if (self.calibrateX != calibrateX) or force or (self.scanx is None):
  170. self.calibrateX = calibrateX
  171. self.scanx = []
  172. for adc in range(self.adcNumber):
  173. dat = np.array(self.scanData[adc])
  174. if calibrateX:
  175. scanx = np.array([theCalibration.calibrateX(adc, val[2], val[3], val[4], id=self.calibId, c25b=val[6]) for val in dat])
  176. else:
  177. scanx = np.array([val[2]*330 + val[3]*25 + val[4]*3 + (4-val[6])*25 for val in dat])*1e-12
  178. self.scanx.append(scanx)
  179. if (self.calibrateY != calibrateY) or force or (self.scany is None) or (self.bunch != bunch):
  180. self.calibrateY = calibrateY
  181. self.scany = []
  182. self.scane = []
  183. self.bunch = bunch
  184. for adc in range(self.adcNumber):
  185. dat = np.array(self.scanData[adc])
  186. if self.multibunch:
  187. scany = np.array(self.multibunchData[adc])[:,bunch]
  188. if calibrateY:
  189. scany = theCalibration.calibrateY(scany, adc, id=self.calibId)
  190. scane = np.array(self.multibunchStd[adc])[:,bunch]
  191. else:
  192. scany = dat.T[0]
  193. if calibrateY:
  194. scany = theCalibration.calibrateY(scany, adc, id=self.calibId)
  195. scane = dat.T[1]
  196. self.scany.append(scany)
  197. self.scane.append(scane)
  198. #print('_prepareScan --')
  199. #scanx = scanx[np.where(data[0,:,6] == 4)]
  200. ###################################################################################################
  201. # .d8888b. 888
  202. # d88P Y88b 888
  203. # 888 888 888
  204. # 888 .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b.
  205. # 888 88888 d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b
  206. # 888 888 88888888 888 888 88888888 888 .d888888 888 88888888
  207. # Y88b d88P Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b.
  208. # "Y8888P88 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888
  209. #
  210. #
  211. #
  212. def prepare(self, adcNumber, multibunch):
  213. self.scanData = [[],[],[],[], [],[],[],[]]
  214. self.adcNumber = adcNumber
  215. self.scanInfo = None
  216. self.scanx = None
  217. self.scany = None
  218. self.scane = None
  219. self.calibrateY = False
  220. self.calibrateX = False
  221. self.multibunch = multibunch
  222. self.bunch = 0
  223. self.multibunchData = [[],[],[],[], [],[],[],[]]
  224. self.multibunchStd = [[],[],[],[], [],[],[],[]]
  225. self.calibId = "current"
  226. pass
  227. def appendData(self, value, error, adc, c330, c25, c3, c25b, c330b=0):
  228. self.appending = True
  229. if self.multibunch:
  230. self.scanData[adc].append([value[0], error[0], c330, c25, c3, c330b, c25b])
  231. self.multibunchData[adc].append(value)
  232. self.multibunchStd[adc].append(error)
  233. else:
  234. self.scanData[adc].append([value, error, c330, c25, c3, c330b, c25b])
  235. self.appending = False
  236. def saveScan(self, filename, index, info, threshold,
  237. c_min, c_max, c25_min, c25_max,
  238. f_min, f_max, stop, c_step, c25_step, f_step,
  239. step4, mode, fastMode, calibrationScan
  240. ):
  241. fileinfo = os.path.join(os.path.dirname(filename), 'scan.info')
  242. f = open(filename, 'w')
  243. self.fileName = filename
  244. path = os.path.dirname(os.path.dirname(self.fileName))
  245. self.calibId = theCalibration.openFile(os.path.join(path,'calibration.hdf'))
  246. if fastMode:
  247. f.write('#FastMode\n')
  248. for adc in range(self.adcNumber):
  249. f.write("#ADC_%s\n" % adc)
  250. f.write("#330ps;25ps;3ps;mean;std;330psB;25psB\n")
  251. for i, item in enumerate(self.scanData[adc]):
  252. if self.multibunch:
  253. f.write("{:02d};{:02d};{:02d};{};{};{:02d};{:02d}\n".format(item[2], item[3], item[4],
  254. np.array2string(np.array(self.multibunchData[adc][i]), precision=2, separator=',', threshold=2000, max_line_width=10000000)[1:-1],
  255. np.array2string(np.array(self.multibunchStd[adc][i]), precision=2, separator=',', threshold=2000, max_line_width=10000000)[1:-1],
  256. item[5], item[6]))
  257. else:
  258. f.write("{:02d};{:02d};{:02d};{:0.3f};{:0.3f};{:02d};{:02d}\n".format(item[2], item[3], item[4], item[0], item[1], item[5], item[6]))
  259. f.write('\n')
  260. f.close()
  261. f = open(fileinfo, 'a')
  262. f.write('Scan\n')
  263. f.write('Nr: {}\n'.format(index))
  264. f.write('File: {}\n'.format(os.path.basename(filename)))
  265. f.write('Info: {}\n'.format(info))
  266. f.write('Threshold: {}\n'.format(threshold))
  267. #f.write('ADC to T/H: {} + {}\n'.format(bif.bk_get_config(self.board_id, 'delay_330_adc'), bif.bk_get_config(self.board_id, 'delay_25_adc')))
  268. f.write('Range\n')
  269. f.write('\t T/H: {}-{}\n'.format(c_min, c_max))
  270. f.write('\t 25ps: {}-{}\n'.format(c25_min, c25_max))
  271. f.write('\t fine: {}-{}\n'.format(f_min, f_max))
  272. f.write('Step4: {}\n'.format(step4))
  273. if stop:
  274. f.write('Scan Stopped at: {},{},{}\n'.format(c_step, c25_step, f_step))
  275. f.write('Mode: {}\n'.format(mode))
  276. f.write('Fast Mode: {}\n'.format(fastMode))
  277. f.write('Calibration: {}\n'.format(calibrationScan))
  278. f.write('\n')
  279. f.close()
  280. ###################################################################################################
  281. ###################################################################################################