dataset.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import logging
  2. import time
  3. import numpy as np
  4. from numpy.polynomial.polynomial import polyval
  5. from ... import config
  6. def _pad_array(array):
  7. height, width = array.shape
  8. # Miriam uses floor hence the padding is actually a cutting. Will wait for
  9. # response if this is desired ...
  10. pwidth = 2**np.floor(np.log2(width))
  11. padded = np.zeros((height, pwidth))
  12. padded[:, :width] = array[:, :pwidth]
  13. return padded
  14. try:
  15. import reikna.cluda
  16. import reikna.fft
  17. _plans = {}
  18. _in_buffers = {}
  19. _out_buffers = {}
  20. _api = reikna.cluda.ocl_api()
  21. _thr = _api.Thread.create()
  22. def _fft(array):
  23. start = time.time()
  24. padded = _pad_array(array).astype(np.complex64)
  25. height, width = padded.shape
  26. if width in _plans:
  27. fft = _plans[width]
  28. in_dev = _in_buffers[width]
  29. out_dev = _out_buffers[width]
  30. else:
  31. fft = reikna.fft.FFT(padded, axes=(1,)).compile(_thr)
  32. in_dev = _thr.to_device(padded)
  33. out_dev = _thr.empty_like(in_dev)
  34. _plans[width] = fft
  35. _in_buffers[width] = in_dev
  36. _out_buffers[width] = out_dev
  37. fft(out_dev, in_dev)
  38. logging.debug("GPU fft: {} s".format(time.time() - start))
  39. return out_dev.get()[:, :width / 2 + 1]
  40. except ImportError:
  41. logging.debug("Failed to import reikna package. Falling back to Numpy FFT.")
  42. def _fft(array):
  43. start = time.time()
  44. freqs = np.fft.rfft(_pad_array(array))
  45. logging.debug("np fft: {} s".format(time.time() - start))
  46. return freqs
  47. BUNCHES_PER_TURN = 184
  48. HEADER_SIZE_BYTES = 32
  49. class DataSet(object):
  50. def __init__(self, array, filename, header=None):
  51. self.filename = filename
  52. self.array = array
  53. self._heatmaps = {}
  54. self._ffts = {}
  55. self.header = header
  56. @property
  57. def skipped_turns(self):
  58. if self.header:
  59. return self.header['skipped_turns']
  60. else:
  61. return 1
  62. def bunch(self, number):
  63. return self.array[self.array[:, 4] == number]
  64. def num_bunches(self):
  65. return self.array.shape[0]
  66. def num_turns(self):
  67. return self.num_bunches() / BUNCHES_PER_TURN
  68. def heatmap(self, adc=1, frm=0, to=-1, bunch_frm=0, bunch_to=-1):
  69. if not 1 <= adc <= 4:
  70. raise ValueError('adc must be in [1,4]')
  71. if not adc in self._heatmaps:
  72. heatmap = self.array[:,adc-1].reshape(-1, BUNCHES_PER_TURN).transpose()
  73. self._heatmaps[adc] = heatmap
  74. return self._heatmaps[adc][bunch_frm:bunch_to, frm:to]
  75. def fft(self, adc=1, frm=0, to=-1, drop_first_bin=False):
  76. if not 1 <= adc <= 4:
  77. raise ValueError('adc must be in [1,4]')
  78. # if not adc in self._ffts:
  79. # heatmap = self.heatmap(adc, frm, to)
  80. # self._ffts[adc] = np.fft.fft2(heatmap, axes=[1])
  81. # return self._ffts[adc]
  82. heatmap = self.heatmap(adc, frm, to)
  83. if drop_first_bin:
  84. return _fft(heatmap)[:, 1:]
  85. else:
  86. return _fft(heatmap)
  87. def fft_max_freq(self):
  88. return (self.num_turns() // 2 + 1) * self.fft_freq_dist()
  89. def fft_freq_dist(self):
  90. return 1.0/(self.num_turns() * (self.skipped_turns + 1) * config.tRev)
  91. def train(self, adc=1, frm=0, to=-1, **kwargs):
  92. pdata = self.array[frm:to, :-1]
  93. return pdata[:,adc-1]
  94. def combined(self, frm=0, to=-1, show_reconstructed=True):
  95. array = self.array[frm:to, :]
  96. N_s = 16
  97. N_p = array.shape[0]
  98. # Remove bunch number and flatten array
  99. array = array[:,:4].reshape((-1, 1))
  100. array = array.flatten()
  101. # plot original data
  102. orig_xs = np.arange(0, array.shape[0])
  103. # axis.plot(orig_xs, array, '.')
  104. ret = [np.array([orig_xs, array])]
  105. # 4 rows for each ADC
  106. ys = array.reshape((4, -1), order='F')
  107. # multi-fit for each column of 4 ADCs, unfortunately, xs' are always the
  108. # same, so we have to offset them later when computing the value
  109. xs = [1, 2, 3, 4]
  110. c = np.polynomial.polynomial.polyfit(xs, ys, 6)
  111. smooth_xs = np.linspace(1, 4, N_s)
  112. fitted_ys = polyval(smooth_xs, c, tensor=True)
  113. if True:
  114. # Output maxima
  115. ys = np.max(fitted_ys, axis=1)
  116. xs = 4 * ((np.argmax(fitted_ys, axis=1) + 1) / float(N_s)) + orig_xs[::4] - .5
  117. # axis.plot(xs, ys, '.', color="red")
  118. ret.append(np.array([xs, ys]))
  119. if False:
  120. # Debug output
  121. ys = fitted_ys.reshape((-1, 1))
  122. ys = ys.flatten()
  123. xs = np.repeat(np.arange(0, 4 * N_p, 4), N_s) + np.tile(np.linspace(0, 3, N_s), N_p)
  124. # axis.plot(xs, ys, '.', alpha=0.3)
  125. ret.append(np.array([xs, ys]))
  126. return ret