1_block_synchronizer.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import pypulseq as puls
  2. import numpy as np
  3. import json
  4. from matplotlib import pyplot as plt
  5. seq_file = "seq_storage/SE_rfdeath_5000.seq"
  6. seq_input = puls.Sequence()
  7. seq_input.read(file_path=seq_file)
  8. seq_output_dict = seq_input.waveforms_export(time_range=(0, 3))
  9. def output_seq(dict):
  10. loc_t_adc = dict['t_adc']
  11. loc_t_rf = dict['t_rf']
  12. loc_t_rf_centers = dict['t_rf_centers']
  13. loc_t_gx = dict['t_gx']
  14. loc_t_gy = dict['t_gy']
  15. loc_t_gz = dict['t_gz']
  16. loc_adc = dict['adc']
  17. loc_rf = dict['rf']
  18. loc_rf_centers = dict['rf_centers']
  19. loc_gx = dict['gx']
  20. loc_gy = dict['gy']
  21. loc_gz = dict['gz']
  22. with open('data_output_seq/t_adc.txt', 'w') as f:
  23. data = str(tuple(loc_t_adc))
  24. f.write(data)
  25. with open('data_output_seq/t_rf.txt', 'w') as f:
  26. data = str(tuple(loc_t_rf))
  27. f.write(data)
  28. with open('data_output_seq/t_rf_centers.txt', 'w') as f:
  29. data = str(tuple(loc_t_rf_centers))
  30. f.write(data)
  31. with open('data_output_seq/t_gx.txt', 'w') as f:
  32. data = str(tuple(loc_t_gx))
  33. f.write(data)
  34. with open('data_output_seq/t_gy.txt', 'w') as f:
  35. data = str(tuple(loc_t_gy))
  36. f.write(data)
  37. with open('data_output_seq/t_gz.txt', 'w') as f:
  38. data = str(tuple(loc_t_gz))
  39. f.write(data)
  40. with open('data_output_seq/adc.txt', 'w') as f:
  41. data = str(tuple(loc_adc))
  42. f.write(data)
  43. with open('data_output_seq/rf.txt', 'w') as f:
  44. data = str(tuple(loc_rf))
  45. f.write(data)
  46. with open('data_output_seq/rf_centers.txt', 'w') as f:
  47. data = str(tuple(loc_rf_centers))
  48. f.write(data)
  49. with open('data_output_seq/gx.txt', 'w') as f:
  50. data = str(tuple(loc_gx))
  51. f.write(data)
  52. with open('data_output_seq/gy.txt', 'w') as f:
  53. data = str(tuple(loc_gy))
  54. f.write(data)
  55. with open('data_output_seq/gz.txt', 'w') as f:
  56. data = str(tuple(loc_gz))
  57. f.write(data)
  58. output_seq(seq_output_dict)
  59. # added type check in Sequence.block, read does not make an empty variable with a type
  60. # is there the other way to do it?
  61. # print(seq_output_dict['gx'])
  62. # Engage what exactly every array means
  63. # print(seq_input.waveforms_and_times())
  64. # plt.plot()
  65. # plt.show()
  66. # print(seq_output_dict)
  67. # t_adc t_rf t_rf_centers t_gx t_gy t_gz adc rf rf_centers gx gy gz
  68. # seq_input.plot()
  69. # plt.plot(seq_output_dict['t_rf'], seq_output_dict['rf'])
  70. # plt.show()
  71. # plt.plot(seq_output_dict['t_adc'], seq_output_dict['adc'])
  72. # plt.show()
  73. local_definitions = seq_input.definitions
  74. ADC_raster = local_definitions['AdcRasterTime']
  75. RF_raster = local_definitions['RadiofrequencyRasterTime']
  76. RF_dtime = 100 * 1e-6
  77. TR_dtime = 100 * 1e-6
  78. # artificial delays
  79. time_info = seq_input.duration()
  80. blocks_number = time_info[1]
  81. time_dur = time_info[0]
  82. time_step = 20 * 1e-9
  83. N_samples = int(time_dur / time_step)
  84. # TODO: why two times bigger? what effort on output
  85. time_sample = np.linspace(0, time_dur, N_samples)
  86. gate_adc = np.zeros(N_samples)
  87. gate_rf = np.zeros(N_samples)
  88. gate_tr_switch = np.ones(N_samples)
  89. gate_gx = np.zeros(N_samples)
  90. gate_gy = np.zeros(N_samples)
  91. gate_gz = np.zeros(N_samples)
  92. local_delay_rf = RF_dtime
  93. local_delay_tr = TR_dtime
  94. local_raster_time = time_step
  95. # TODO: function defining beginning and ending of the RF events
  96. RF_assintant = [seq_output_dict['t_rf'][0] - RF_dtime, seq_output_dict['t_rf'][-1]]
  97. def gates_output(gates, synchro_impulse=20 * 1e-9):
  98. for i_loc in range(len(gates['gx'])):
  99. a = 1
  100. with open('data_output/tr_switch.txt', 'w') as f:
  101. data = str(tuple(gates['tr_switch']))
  102. f.write(data)
  103. with open('data_output/rf.txt', 'w') as f:
  104. data = str(tuple(gates['rf']))
  105. f.write(data)
  106. with open('data_output/adc.txt', 'w') as f:
  107. data = str(tuple(gates['adc']))
  108. f.write(data)
  109. data = {'gate_gx': tuple(gates['gx']),
  110. 'gate_gy': tuple(gates['gy']),
  111. 'gate_gz': tuple(gates['gz'])}
  112. with open('data_output/gradient_gates.json', 'w') as outfile:
  113. json.dump(data, outfile)
  114. def adc_correction():
  115. rise_time, fall_time = None, None
  116. is_adc_inside = False
  117. for j in range(blocks_number - 1):
  118. iterable_block = seq_input.get_block(block_index=j + 1)
  119. if iterable_block.adc is not None:
  120. is_adc_inside = True
  121. rise_time = iterable_block.gx.rise_time
  122. fall_time = iterable_block.gx.fall_time
  123. if not is_adc_inside:
  124. raise Exception("No ADC event found inside sequence")
  125. return rise_time, fall_time
  126. def adc_event_edges(local_gate_adc):
  127. num_begin_l = 0
  128. flag_begin = False
  129. flag_finish = False
  130. num_finish_l = 1
  131. for k in range(len(local_gate_adc) - 1):
  132. if local_gate_adc[k] != 0 and not flag_begin:
  133. num_begin_l = k
  134. flag_begin = True
  135. if local_gate_adc[k] != 0 and local_gate_adc[k + 1] == 0 and not flag_finish:
  136. num_finish_l = k
  137. flag_finish = True
  138. return num_begin_l, num_finish_l
  139. for i in range(N_samples):
  140. # delaying of RF event for time period of local delay
  141. if RF_assintant[0] - RF_raster < time_sample[i] < RF_assintant[0] + RF_raster:
  142. RF_stop = int(RF_assintant[1] / time_step)
  143. gate_rf[i:RF_stop] = 1.0
  144. var = 1
  145. # mandatory disabling of RF gate due to ADC work same time
  146. gate_rf_2 = map(lambda x: time_sample[i] - ADC_raster < x < time_sample[i] + ADC_raster and 1 or 0,
  147. seq_output_dict['t_adc'])
  148. if np.any(np.array(list(gate_rf_2)) > 0):
  149. gate_rf[i] = 0.0
  150. # TR switch with own delay before ADC turning
  151. gate_tr_1 = map(lambda x: time_sample[i] - ADC_raster < x < time_sample[i] + ADC_raster and 1 or 0,
  152. seq_output_dict['t_adc'])
  153. if np.any(np.array(list(gate_tr_1)) > 0):
  154. block_delay_tr = int(local_delay_tr / time_step)
  155. gate_tr_switch[i - block_delay_tr:i + 1] = 0.0
  156. # first step of ADC gate - enabling
  157. # TODO: ADC gate feeling gradients form of rise and fall
  158. gate_adc_1 = map(lambda x: time_sample[i] - ADC_raster < x < time_sample[i] + ADC_raster and 1 or 0,
  159. seq_output_dict['t_adc'])
  160. if np.any(np.array(list(gate_adc_1)) > 0):
  161. gate_adc[i] = 1.0
  162. # adc correction sue to rise and fall time of gradient
  163. # defining time that ADC need to be disabled during of
  164. rise_time_loc, fall_time_loc = adc_correction()
  165. num_beg, num_fin = adc_event_edges(gate_adc)
  166. rise_time_tick = int(rise_time_loc / time_step)
  167. fall_time_tick = int(rise_time_loc / time_step)
  168. gate_adc[num_beg:num_beg + rise_time_tick] = 0.0
  169. gate_adc[num_fin - fall_time_tick:num_fin + 1] = 0.0
  170. gates_release = {"adc": gate_adc,
  171. "rf": gate_rf,
  172. "tr_switch": gate_tr_switch,
  173. "gx": gate_gx,
  174. "gy": gate_gy,
  175. "gz": gate_gz}
  176. # plt.plot(seq_output_dict['t_gx'][:int(N_samples)], seq_output_dict['gx'][:int(N_samples)])
  177. # plt.plot(seq_output_dict['t_gy'][:int(N_samples)], seq_output_dict['gy'][:int(N_samples)])
  178. # plt.plot(seq_output_dict['t_gz'][:int(N_samples)], seq_output_dict['gz'][:int(N_samples)])
  179. # plt.show()
  180. #
  181. # plt.plot(seq_output_dict['t_gx'][:int(N_samples)], seq_output_dict['gx'][:int(N_samples)] / 720)
  182. # plt.plot(time_sample[:int(N_samples)], gate_adc[:int(N_samples)], label='ADC gate')
  183. # plt.plot(time_sample[:int(N_samples)], gate_tr_switch[:int(N_samples)], label='TR switch')
  184. # plt.plot(seq_output_dict['t_rf'], seq_output_dict['rf'] / 210, label='RF signal')
  185. # plt.plot(time_sample[:int(N_samples)], gate_rf[:int(N_samples)], label='RF gate')
  186. # plt.legend()
  187. # plt.show()
  188. # gates_output(gates_release)