TSE_k_space_fill.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. import numpy as np
  2. import random
  3. from copy import deepcopy
  4. def TSE_k_space_fill(n_ex, ETL, k_steps, TE_eff_number, N_center, order, dummy, N_dummy):
  5. # function defines phase encoding steps for k space filling in liner order
  6. # with shifting according to the TE effective number
  7. if dummy:
  8. k_space_dummy_temp = ['dummy']*ETL
  9. k_space_dummy = []
  10. for i in range(N_dummy):
  11. k_space_dummy.append(k_space_dummy_temp)
  12. k_space_list_with_zero = []
  13. for i in range(ETL):
  14. #k_space_list_with_zero.append(int((ETL - 1) * n_ex - i * n_ex))
  15. k_space_list_with_zero.append(i * n_ex)
  16. if n_ex > 1:
  17. k_space_order_filing_temp = [k_space_list_with_zero]
  18. for i in range(n_ex - 1):
  19. k_space_list_temp = []
  20. for k in k_space_list_with_zero:
  21. k_space_list_temp.append(k + i + 1)
  22. k_space_order_filing_temp.append(k_space_list_temp)
  23. else:
  24. k_space_order_filing_temp = [k_space_list_with_zero]
  25. kk = 0
  26. for k_space_list_with_central_old in k_space_order_filing_temp:
  27. temporal = abs(k_space_list_with_central_old - N_center)
  28. center_index = np.argmin(temporal)
  29. central_line_position_old = center_index
  30. num_left_old = central_line_position_old
  31. num_right_old = len(k_space_list_with_central_old) - num_left_old - 1
  32. for i in range(len(k_space_list_with_central_old)):
  33. if k_space_list_with_central_old[i] > (k_steps - 1):
  34. k_space_list_with_central_old[i] = 'skip'
  35. k_space_list_with_central_new = ['skip'] * len(k_space_list_with_central_old)
  36. central_line_position_new = TE_eff_number - 1
  37. num_left_new = central_line_position_new
  38. num_right_new = len(k_space_list_with_central_new) - num_left_new - 1
  39. if num_left_new < num_right_new:
  40. min_new = num_left_new
  41. max_new = num_right_new
  42. else:
  43. min_new = num_right_new
  44. max_new = num_left_new
  45. k_space_list_with_central_new[central_line_position_new] = k_space_list_with_central_old[
  46. central_line_position_old]
  47. k_space_list_with_central_old[central_line_position_old] = 'passed'
  48. if min_new == 0: # effective time is first one
  49. i = 0
  50. k_space_list_with_central_old_abs = [0] * len(k_space_list_with_central_old)
  51. for ii in range(len(k_space_list_with_central_old)):
  52. if k_space_list_with_central_old[ii] != 'skip' and k_space_list_with_central_old[ii] != 'passed':
  53. k_space_list_with_central_old_abs[ii] = abs(k_space_list_with_central_old[ii] - N_center)
  54. #type_of_elements = type(k_space_list_with_central_old_abs[0])
  55. else:
  56. k_space_list_with_central_old_abs[ii] = k_space_list_with_central_old[ii]
  57. #type_of_elements = type(k_space_list_with_central_old_abs[0])
  58. type_of_string = type('passed')
  59. if num_left_new < num_right_new:
  60. flag = True
  61. j = central_line_position_new + i + 1
  62. while flag:
  63. a = min(filter(lambda i: not isinstance(i, type_of_string), k_space_list_with_central_old_abs))
  64. min_index = k_space_list_with_central_old_abs.index(a)
  65. k_space_list_with_central_new[j] = k_space_list_with_central_old[min_index]
  66. k_space_list_with_central_old_abs[min_index] = 'passed'
  67. k_space_list_with_central_old[min_index] = 'passed'
  68. j += 1
  69. flag = any(not isinstance(y, (type_of_string)) for y in k_space_list_with_central_old)
  70. k_space_order_filing_temp[kk] = k_space_list_with_central_new
  71. kk += 1
  72. else:
  73. flag = True
  74. j = central_line_position_new - i - 1
  75. while flag:
  76. a = min(filter(lambda i: not isinstance(i, type_of_string), k_space_list_with_central_old_abs))
  77. min_index = k_space_list_with_central_old_abs.index(a)
  78. k_space_list_with_central_new[j] = k_space_list_with_central_old[min_index]
  79. k_space_list_with_central_old_abs[min_index] = 'passed'
  80. k_space_list_with_central_old[min_index] = 'passed'
  81. j -= 1
  82. flag = any(not isinstance(y, (type_of_string)) for y in k_space_list_with_central_old)
  83. k_space_order_filing_temp[kk] = k_space_list_with_central_new
  84. kk += 1
  85. else:
  86. for i in range(1, min_new + 1):
  87. k_space_list_with_central_new[central_line_position_new + i] = k_space_list_with_central_old[
  88. central_line_position_old + i]
  89. k_space_list_with_central_old[central_line_position_old + i] = 'passed'
  90. k_space_list_with_central_new[central_line_position_new - i] = k_space_list_with_central_old[
  91. central_line_position_old - i]
  92. k_space_list_with_central_old[central_line_position_old - i] = 'passed'
  93. k_space_list_with_central_old_abs = [0] * len(k_space_list_with_central_old)
  94. for ii in range(len(k_space_list_with_central_old)):
  95. if k_space_list_with_central_old[ii] != 'skip' and k_space_list_with_central_old[ii] != 'passed':
  96. k_space_list_with_central_old_abs[ii] = abs(k_space_list_with_central_old[ii] - N_center)
  97. #type_of_elements = type(k_space_list_with_central_old_abs[0])
  98. else:
  99. k_space_list_with_central_old_abs[ii] = k_space_list_with_central_old[ii]
  100. #type_of_elements = type(k_space_list_with_central_old_abs[0])
  101. type_of_string = type('passed')
  102. if num_left_new < num_right_new:
  103. flag = True
  104. j = central_line_position_new + i + 1
  105. while flag:
  106. a = min(filter(lambda i: not isinstance(i, type_of_string), k_space_list_with_central_old_abs))
  107. min_index = k_space_list_with_central_old_abs.index(a)
  108. k_space_list_with_central_new[j] = k_space_list_with_central_old[min_index]
  109. k_space_list_with_central_old_abs[min_index] = 'passed'
  110. k_space_list_with_central_old[min_index] = 'passed'
  111. j += 1
  112. flag = any(not isinstance(y, (type_of_string)) for y in k_space_list_with_central_old)
  113. k_space_order_filing_temp[kk] = k_space_list_with_central_new
  114. kk += 1
  115. else:
  116. flag = True
  117. j = central_line_position_new - i - 1
  118. while flag:
  119. a = min(filter(lambda i: not isinstance(i, type_of_string), k_space_list_with_central_old_abs))
  120. min_index = k_space_list_with_central_old_abs.index(a)
  121. k_space_list_with_central_new[j] = k_space_list_with_central_old[min_index]
  122. k_space_list_with_central_old_abs[min_index] = 'passed'
  123. k_space_list_with_central_old[min_index] = 'passed'
  124. j -= 1
  125. flag = any(not isinstance(y, (type_of_string)) for y in k_space_list_with_central_old)
  126. k_space_order_filing_temp[kk] = k_space_list_with_central_new
  127. kk += 1
  128. #k_space_order_filing = k_space_order_filing.append(k_space_list_with_central_new)
  129. """
  130. k_space_order_filing = []
  131. n_ex_shift = np.int64(n_ex/2)-1
  132. a = range(0-n_ex_shift, n_ex-n_ex_shift)
  133. for i in a:
  134. k_space_list_temp = []
  135. for kk in k_space_list_with_central_new:
  136. value = kk + i
  137. if value < 0:
  138. value = value + k_steps
  139. if value > k_steps - 1:
  140. value = 'skip'
  141. k_space_list_temp.append(value)
  142. k_space_order_filing.append(k_space_list_temp)
  143. """
  144. if dummy:
  145. for list in k_space_order_filing_temp:
  146. k_space_dummy.append(list)
  147. else:
  148. k_space_dummy = k_space_order_filing_temp
  149. return k_space_dummy
  150. def HASTE_k_space_fill(n_ex, ETL, k_steps, TE_eff_number, N_center, order, dummy, N_dummy, params):
  151. # function defines phase encoding steps for k space filling in liner order
  152. # with shifting according to the TE effective number
  153. if dummy:
  154. k_space_dummy_temp = ['dummy']*k_steps
  155. k_space_dummy = []
  156. for i in range(N_dummy):
  157. k_space_dummy.append(k_space_dummy_temp)
  158. k_space_list = [*range(0, k_steps)]
  159. eff_shift = TE_eff_number - N_center - 1
  160. if params['part_fourier_factor_phase'] == 1.0:
  161. k_space_list_reordered = np.roll(k_space_list, shift=eff_shift)
  162. if TE_eff_number < int(k_space_list_reordered.size / 2):
  163. first_descrim = (TE_eff_number * 2)
  164. temp_list_second = k_space_list_reordered[first_descrim:]
  165. temp_list_first = k_space_list_reordered[:first_descrim]
  166. temp_list_reordered = np.empty([int(temp_list_second.size)], dtype=int)
  167. for i in range(int(temp_list_reordered.size / 2)):
  168. print(i)
  169. temp_list_reordered[2 * i + 1] = temp_list_second[-1 - i]
  170. temp_list_reordered[2 * i] = temp_list_second[i]
  171. k_space_list_reordered = np.concatenate((temp_list_first, temp_list_reordered), axis=None)
  172. else:
  173. k_space_list_reordered = np.roll(k_space_list, shift=eff_shift)
  174. zero_index = k_space_list_reordered.tolist().index(0)
  175. temp_list = k_space_list_reordered[zero_index:]
  176. temp_list = temp_list[::-1]
  177. temp_max_list = k_space_list_reordered[:zero_index]
  178. k_space_list_reordered = np.concatenate((temp_max_list, temp_list), axis=None)
  179. if order == "non_linear":
  180. pass
  181. elif order == "random":
  182. q1 = params['Np'] // 3
  183. q2 = (params['Np'] - q1) // 2
  184. q3 = params['Np'] - q1 - q2
  185. # TODO: random sampling
  186. #list_q1 = k_space_list_reordered[:q1]
  187. #if q2 > len(k_space_list_reordered):
  188. # list_q2 = k_space_list_reordered[q1:q1+q2]
  189. # list_q3 = k_space_list_reordered[q2:]
  190. #else:
  191. # list_q2 = k_space_list_reordered[q1:]
  192. # list_q3 = []
  193. #list_q1, list_q3 = redistribute_randomly_same_size(list_q1, list_q3)
  194. #k_space_list_reordered = list_q1 + list_q2 + list_q3
  195. else:
  196. print("That's not a valid order.") # Default case
  197. if dummy:
  198. k_space_dummy.append(k_space_list_reordered.tolist())
  199. else:
  200. k_space_dummy = [k_space_list_reordered.tolist()]
  201. return k_space_dummy
  202. def redistribute_randomly_same_size(list1, list2):
  203. combined = list1 + list2
  204. random.shuffle(combined)
  205. size1 = len(list1)
  206. size2 = len(list2)
  207. new_list1 = combined[:size1]
  208. new_list2 = combined[size1:size1 + size2]
  209. return new_list1, new_list2
  210. def circle_2D_filling_TSE(Nx, Ny, Nx_center, Ny_center, target_pixels, N_points, previous_pixels):
  211. # Начальный радиус (по формуле площади круга)
  212. radius = np.sqrt(target_pixels / np.pi)
  213. num_iteration = int(target_pixels / N_points)
  214. while True:
  215. # Список пикселей внутри круга
  216. selected_pixels = []
  217. for x in range(Nx):
  218. for y in range(Ny):
  219. if (x - Nx_center) ** 2 + (y - Ny_center) ** 2 <= radius ** 2:
  220. selected_pixels.append((x, y))
  221. # print(len(selected_pixels))
  222. if (len(selected_pixels) >= target_pixels):
  223. break
  224. # Корректируем радиус: уменьшаем, если пикселей много, увеличиваем, если мало
  225. if len(selected_pixels) < target_pixels:
  226. radius += 0.1 # Увеличиваем радиус
  227. selected_pixels_final = [x for x in selected_pixels if x not in previous_pixels]
  228. selected_pixels_final = selected_pixels_final[:N_points]
  229. # print(len(selected_pixels_final))
  230. '''
  231. # Создаем изображение
  232. image = np.zeros((Nx, Ny))
  233. for x, y in selected_pixels_final:
  234. image[y, x] = 1 # Заполняем белым цветом
  235. # Визуализация
  236. plt.imshow(image, cmap="gray", origin="lower")
  237. plt.scatter(Nx_center, Ny_center, color="red", marker="x") # Отмечаем центр
  238. plt.grid(visible=True, color="red", linestyle="--", linewidth=0.5)
  239. plt.title(f"Круг из {len(selected_pixels_final)} пикселей")
  240. plt.show()
  241. '''
  242. return selected_pixels_final
  243. def circle_2D_filling_TSE_last_acq(Nx, Ny, previous_pixels, N_points):
  244. all_pixels = []
  245. for x in range(Nx):
  246. for y in range(Ny):
  247. all_pixels.append((x, y))
  248. selected_pixels_final = [x for x in all_pixels if x not in previous_pixels]
  249. '''
  250. image = np.zeros((Nx, Ny))
  251. for x, y in selected_pixels_final:
  252. image[y, x] = 1 # Заполняем белым цветом
  253. # Визуализация
  254. plt.imshow(image, cmap="gray", origin="lower")
  255. plt.scatter(Nx_center, Ny_center, color="red", marker="x") # Отмечаем центр
  256. plt.grid(visible=True, color="red", linestyle="--", linewidth=0.5)
  257. plt.title(f"Круг из {len(selected_pixels_final)} пикселей")
  258. plt.show()
  259. '''
  260. if len(selected_pixels_final) == 0:
  261. return None
  262. elif (selected_pixels_final) != N_points:
  263. for i in range(N_points - len(selected_pixels_final)):
  264. selected_pixels_final.append(('skip', 'skip'))
  265. # print(len(selected_pixels_final))
  266. return selected_pixels_final
  267. elif (selected_pixels_final) == N_points:
  268. return selected_pixels_final
  269. def effective_TE_reorder(num_te_eff, num_echo):
  270. if num_te_eff <= num_echo / 2:
  271. a_right = list(range(1, (num_te_eff - 1) * 2, 2))
  272. a_left = list(range((num_te_eff - 1) * 2, 1, -2))
  273. a = a_left + [0] + a_right
  274. a_end = list(range(len(a), num_echo))
  275. a_final = a + a_end
  276. elif num_te_eff > num_echo / 2:
  277. k = num_echo - num_te_eff + 1
  278. a_right = list(range(1, (k - 1) * 2, 2))
  279. a_left = list(range((k - 1) * 2, 1, -2))
  280. a = a_left + [0] + a_right
  281. a_end = list(range(num_echo - 1, len(a) - 1, -1))
  282. a_final = a_end + a
  283. return a_final
  284. def k_space_filling_3D_TSE(Ny, Nz, Ny_center, Nz_center, num_echo, num_te_eff, dummy, N_dummy):
  285. num_echo #ETL
  286. #TODO: add
  287. if Ny * Nz % num_echo == 0:
  288. N_points = int(Ny * Nz / num_echo)
  289. else:
  290. N_points = int(Ny * Nz / num_echo ) + 1 # number TE
  291. previous_pixels = []
  292. #Ny = 32
  293. #Nz = 32
  294. #Ny_center = 25
  295. #Nz_center = 25
  296. num_sat = int(Ny * Nz / N_points) # number os saturations
  297. print(num_sat)
  298. if dummy:
  299. k_space_dummy_temp =[]
  300. for i in range(num_echo):
  301. k_space_dummy_temp.append(('dummy', 'dummy'))
  302. k_space_dummy = []
  303. for i in range(N_dummy):
  304. k_space_dummy.append(k_space_dummy_temp)
  305. k_space_fill = []
  306. for i in range(num_sat):
  307. target_num_points = (i + 1) * N_points
  308. selected_pixels = circle_2D_filling_TSE(Ny, Nz, Ny_center, Nz_center, target_num_points, N_points, previous_pixels)
  309. k_space_fill.append(selected_pixels)
  310. previous_pixels = previous_pixels + selected_pixels
  311. last_k_space_volume = circle_2D_filling_TSE_last_acq(Ny, Nz, previous_pixels, N_points)
  312. if last_k_space_volume != None:
  313. k_space_fill.append(last_k_space_volume)
  314. if num_sat + 1 == num_echo:
  315. pass
  316. else:
  317. k_space_skip_temp = []
  318. for i in range( N_points):
  319. k_space_skip_temp.append(('skip', 'skip'))
  320. for i in range(num_echo - num_sat - 1):
  321. k_space_fill.append(k_space_skip_temp)
  322. eff_TE_reordered = effective_TE_reorder(num_te_eff, num_echo)
  323. k_space_fill_final = []
  324. for ii in range(len(k_space_fill[0])):
  325. one_line = []
  326. for jj in range(len(k_space_fill)):
  327. one_line.append(k_space_fill[eff_TE_reordered[jj]][ii])
  328. k_space_fill_final.append(one_line)
  329. if dummy:
  330. k_space_fill_final = k_space_dummy + k_space_fill_final
  331. return k_space_fill_final