| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- import numpy as np
- import random
- from copy import deepcopy
- def TSE_k_space_fill(n_ex, ETL, k_steps, TE_eff_number, N_center, order, dummy, N_dummy):
- # function defines phase encoding steps for k space filling in liner order
- # with shifting according to the TE effective number
- if dummy:
- k_space_dummy_temp = ['dummy']*ETL
- k_space_dummy = []
- for i in range(N_dummy):
- k_space_dummy.append(k_space_dummy_temp)
- k_space_list_with_zero = []
- for i in range(ETL):
- #k_space_list_with_zero.append(int((ETL - 1) * n_ex - i * n_ex))
- k_space_list_with_zero.append(i * n_ex)
- if n_ex > 1:
- k_space_order_filing_temp = [k_space_list_with_zero]
- for i in range(n_ex - 1):
- k_space_list_temp = []
- for k in k_space_list_with_zero:
- k_space_list_temp.append(k + i + 1)
- k_space_order_filing_temp.append(k_space_list_temp)
- else:
- k_space_order_filing_temp = [k_space_list_with_zero]
- kk = 0
- for k_space_list_with_central_old in k_space_order_filing_temp:
- temporal = abs(k_space_list_with_central_old - N_center)
- center_index = np.argmin(temporal)
- central_line_position_old = center_index
- num_left_old = central_line_position_old
- num_right_old = len(k_space_list_with_central_old) - num_left_old - 1
- for i in range(len(k_space_list_with_central_old)):
- if k_space_list_with_central_old[i] > (k_steps - 1):
- k_space_list_with_central_old[i] = 'skip'
- k_space_list_with_central_new = ['skip'] * len(k_space_list_with_central_old)
- central_line_position_new = TE_eff_number - 1
- num_left_new = central_line_position_new
- num_right_new = len(k_space_list_with_central_new) - num_left_new - 1
- if num_left_new < num_right_new:
- min_new = num_left_new
- max_new = num_right_new
- else:
- min_new = num_right_new
- max_new = num_left_new
- k_space_list_with_central_new[central_line_position_new] = k_space_list_with_central_old[
- central_line_position_old]
- k_space_list_with_central_old[central_line_position_old] = 'passed'
- if min_new == 0: # effective time is first one
- i = 0
- k_space_list_with_central_old_abs = [0] * len(k_space_list_with_central_old)
- for ii in range(len(k_space_list_with_central_old)):
- if k_space_list_with_central_old[ii] != 'skip' and k_space_list_with_central_old[ii] != 'passed':
- k_space_list_with_central_old_abs[ii] = abs(k_space_list_with_central_old[ii] - N_center)
- #type_of_elements = type(k_space_list_with_central_old_abs[0])
- else:
- k_space_list_with_central_old_abs[ii] = k_space_list_with_central_old[ii]
- #type_of_elements = type(k_space_list_with_central_old_abs[0])
- type_of_string = type('passed')
- if num_left_new < num_right_new:
- flag = True
- j = central_line_position_new + i + 1
- while flag:
- a = min(filter(lambda i: not isinstance(i, type_of_string), k_space_list_with_central_old_abs))
- min_index = k_space_list_with_central_old_abs.index(a)
- k_space_list_with_central_new[j] = k_space_list_with_central_old[min_index]
- k_space_list_with_central_old_abs[min_index] = 'passed'
- k_space_list_with_central_old[min_index] = 'passed'
- j += 1
- flag = any(not isinstance(y, (type_of_string)) for y in k_space_list_with_central_old)
- k_space_order_filing_temp[kk] = k_space_list_with_central_new
- kk += 1
- else:
- flag = True
- j = central_line_position_new - i - 1
- while flag:
- a = min(filter(lambda i: not isinstance(i, type_of_string), k_space_list_with_central_old_abs))
- min_index = k_space_list_with_central_old_abs.index(a)
- k_space_list_with_central_new[j] = k_space_list_with_central_old[min_index]
- k_space_list_with_central_old_abs[min_index] = 'passed'
- k_space_list_with_central_old[min_index] = 'passed'
- j -= 1
- flag = any(not isinstance(y, (type_of_string)) for y in k_space_list_with_central_old)
- k_space_order_filing_temp[kk] = k_space_list_with_central_new
- kk += 1
- else:
- for i in range(1, min_new + 1):
- k_space_list_with_central_new[central_line_position_new + i] = k_space_list_with_central_old[
- central_line_position_old + i]
- k_space_list_with_central_old[central_line_position_old + i] = 'passed'
- k_space_list_with_central_new[central_line_position_new - i] = k_space_list_with_central_old[
- central_line_position_old - i]
- k_space_list_with_central_old[central_line_position_old - i] = 'passed'
- k_space_list_with_central_old_abs = [0] * len(k_space_list_with_central_old)
- for ii in range(len(k_space_list_with_central_old)):
- if k_space_list_with_central_old[ii] != 'skip' and k_space_list_with_central_old[ii] != 'passed':
- k_space_list_with_central_old_abs[ii] = abs(k_space_list_with_central_old[ii] - N_center)
- #type_of_elements = type(k_space_list_with_central_old_abs[0])
- else:
- k_space_list_with_central_old_abs[ii] = k_space_list_with_central_old[ii]
- #type_of_elements = type(k_space_list_with_central_old_abs[0])
- type_of_string = type('passed')
- if num_left_new < num_right_new:
- flag = True
- j = central_line_position_new + i + 1
- while flag:
- a = min(filter(lambda i: not isinstance(i, type_of_string), k_space_list_with_central_old_abs))
- min_index = k_space_list_with_central_old_abs.index(a)
- k_space_list_with_central_new[j] = k_space_list_with_central_old[min_index]
- k_space_list_with_central_old_abs[min_index] = 'passed'
- k_space_list_with_central_old[min_index] = 'passed'
- j += 1
- flag = any(not isinstance(y, (type_of_string)) for y in k_space_list_with_central_old)
- k_space_order_filing_temp[kk] = k_space_list_with_central_new
- kk += 1
- else:
- flag = True
- j = central_line_position_new - i - 1
- while flag:
- a = min(filter(lambda i: not isinstance(i, type_of_string), k_space_list_with_central_old_abs))
- min_index = k_space_list_with_central_old_abs.index(a)
- k_space_list_with_central_new[j] = k_space_list_with_central_old[min_index]
- k_space_list_with_central_old_abs[min_index] = 'passed'
- k_space_list_with_central_old[min_index] = 'passed'
- j -= 1
- flag = any(not isinstance(y, (type_of_string)) for y in k_space_list_with_central_old)
- k_space_order_filing_temp[kk] = k_space_list_with_central_new
- kk += 1
- #k_space_order_filing = k_space_order_filing.append(k_space_list_with_central_new)
- """
- k_space_order_filing = []
- n_ex_shift = np.int64(n_ex/2)-1
- a = range(0-n_ex_shift, n_ex-n_ex_shift)
- for i in a:
- k_space_list_temp = []
- for kk in k_space_list_with_central_new:
- value = kk + i
- if value < 0:
- value = value + k_steps
- if value > k_steps - 1:
- value = 'skip'
- k_space_list_temp.append(value)
- k_space_order_filing.append(k_space_list_temp)
- """
- if dummy:
- for list in k_space_order_filing_temp:
- k_space_dummy.append(list)
- else:
- k_space_dummy = k_space_order_filing_temp
- return k_space_dummy
- def HASTE_k_space_fill(n_ex, ETL, k_steps, TE_eff_number, N_center, order, dummy, N_dummy, params):
- # function defines phase encoding steps for k space filling in liner order
- # with shifting according to the TE effective number
- if dummy:
- k_space_dummy_temp = ['dummy']*k_steps
- k_space_dummy = []
- for i in range(N_dummy):
- k_space_dummy.append(k_space_dummy_temp)
- k_space_list = [*range(0, k_steps)]
- eff_shift = TE_eff_number - N_center - 1
- if params['part_fourier_factor_phase'] == 1.0:
- k_space_list_reordered = np.roll(k_space_list, shift=eff_shift)
- if TE_eff_number < int(k_space_list_reordered.size / 2):
- first_descrim = (TE_eff_number * 2)
- temp_list_second = k_space_list_reordered[first_descrim:]
- temp_list_first = k_space_list_reordered[:first_descrim]
- temp_list_reordered = np.empty([int(temp_list_second.size)], dtype=int)
- for i in range(int(temp_list_reordered.size / 2)):
- print(i)
- temp_list_reordered[2 * i + 1] = temp_list_second[-1 - i]
- temp_list_reordered[2 * i] = temp_list_second[i]
- k_space_list_reordered = np.concatenate((temp_list_first, temp_list_reordered), axis=None)
- else:
- k_space_list_reordered = np.roll(k_space_list, shift=eff_shift)
- zero_index = k_space_list_reordered.tolist().index(0)
- temp_list = k_space_list_reordered[zero_index:]
- temp_list = temp_list[::-1]
- temp_max_list = k_space_list_reordered[:zero_index]
- k_space_list_reordered = np.concatenate((temp_max_list, temp_list), axis=None)
- if order == "non_linear":
- pass
- elif order == "random":
- q1 = params['Np'] // 3
- q2 = (params['Np'] - q1) // 2
- q3 = params['Np'] - q1 - q2
- # TODO: random sampling
- #list_q1 = k_space_list_reordered[:q1]
- #if q2 > len(k_space_list_reordered):
- # list_q2 = k_space_list_reordered[q1:q1+q2]
- # list_q3 = k_space_list_reordered[q2:]
- #else:
- # list_q2 = k_space_list_reordered[q1:]
- # list_q3 = []
- #list_q1, list_q3 = redistribute_randomly_same_size(list_q1, list_q3)
- #k_space_list_reordered = list_q1 + list_q2 + list_q3
- else:
- print("That's not a valid order.") # Default case
- if dummy:
- k_space_dummy.append(k_space_list_reordered.tolist())
- else:
- k_space_dummy = [k_space_list_reordered.tolist()]
- return k_space_dummy
- def redistribute_randomly_same_size(list1, list2):
- combined = list1 + list2
- random.shuffle(combined)
- size1 = len(list1)
- size2 = len(list2)
- new_list1 = combined[:size1]
- new_list2 = combined[size1:size1 + size2]
- return new_list1, new_list2
- def circle_2D_filling_TSE(Nx, Ny, Nx_center, Ny_center, target_pixels, N_points, previous_pixels):
- # Начальный радиус (по формуле площади круга)
- radius = np.sqrt(target_pixels / np.pi)
- num_iteration = int(target_pixels / N_points)
- while True:
- # Список пикселей внутри круга
- selected_pixels = []
- for x in range(Nx):
- for y in range(Ny):
- if (x - Nx_center) ** 2 + (y - Ny_center) ** 2 <= radius ** 2:
- selected_pixels.append((x, y))
- # print(len(selected_pixels))
- if (len(selected_pixels) >= target_pixels):
- break
- # Корректируем радиус: уменьшаем, если пикселей много, увеличиваем, если мало
- if len(selected_pixels) < target_pixels:
- radius += 0.1 # Увеличиваем радиус
- selected_pixels_final = [x for x in selected_pixels if x not in previous_pixels]
- selected_pixels_final = selected_pixels_final[:N_points]
- # print(len(selected_pixels_final))
- '''
- # Создаем изображение
- image = np.zeros((Nx, Ny))
- for x, y in selected_pixels_final:
- image[y, x] = 1 # Заполняем белым цветом
- # Визуализация
- plt.imshow(image, cmap="gray", origin="lower")
- plt.scatter(Nx_center, Ny_center, color="red", marker="x") # Отмечаем центр
- plt.grid(visible=True, color="red", linestyle="--", linewidth=0.5)
- plt.title(f"Круг из {len(selected_pixels_final)} пикселей")
- plt.show()
- '''
- return selected_pixels_final
- def circle_2D_filling_TSE_last_acq(Nx, Ny, previous_pixels, N_points):
- all_pixels = []
- for x in range(Nx):
- for y in range(Ny):
- all_pixels.append((x, y))
- selected_pixels_final = [x for x in all_pixels if x not in previous_pixels]
- '''
- image = np.zeros((Nx, Ny))
- for x, y in selected_pixels_final:
- image[y, x] = 1 # Заполняем белым цветом
- # Визуализация
- plt.imshow(image, cmap="gray", origin="lower")
- plt.scatter(Nx_center, Ny_center, color="red", marker="x") # Отмечаем центр
- plt.grid(visible=True, color="red", linestyle="--", linewidth=0.5)
- plt.title(f"Круг из {len(selected_pixels_final)} пикселей")
- plt.show()
- '''
- if len(selected_pixels_final) == 0:
- return None
- elif (selected_pixels_final) != N_points:
- for i in range(N_points - len(selected_pixels_final)):
- selected_pixels_final.append(('skip', 'skip'))
- # print(len(selected_pixels_final))
- return selected_pixels_final
- elif (selected_pixels_final) == N_points:
- return selected_pixels_final
- def effective_TE_reorder(num_te_eff, num_echo):
- if num_te_eff <= num_echo / 2:
- a_right = list(range(1, (num_te_eff - 1) * 2, 2))
- a_left = list(range((num_te_eff - 1) * 2, 1, -2))
- a = a_left + [0] + a_right
- a_end = list(range(len(a), num_echo))
- a_final = a + a_end
- elif num_te_eff > num_echo / 2:
- k = num_echo - num_te_eff + 1
- a_right = list(range(1, (k - 1) * 2, 2))
- a_left = list(range((k - 1) * 2, 1, -2))
- a = a_left + [0] + a_right
- a_end = list(range(num_echo - 1, len(a) - 1, -1))
- a_final = a_end + a
- return a_final
- def k_space_filling_3D_TSE(Ny, Nz, Ny_center, Nz_center, num_echo, num_te_eff, dummy, N_dummy):
- num_echo #ETL
- #TODO: add
- if Ny * Nz % num_echo == 0:
- N_points = int(Ny * Nz / num_echo)
- else:
- N_points = int(Ny * Nz / num_echo ) + 1 # number TE
- previous_pixels = []
- #Ny = 32
- #Nz = 32
- #Ny_center = 25
- #Nz_center = 25
- num_sat = int(Ny * Nz / N_points) # number os saturations
- print(num_sat)
- if dummy:
- k_space_dummy_temp =[]
- for i in range(num_echo):
- k_space_dummy_temp.append(('dummy', 'dummy'))
- k_space_dummy = []
- for i in range(N_dummy):
- k_space_dummy.append(k_space_dummy_temp)
- k_space_fill = []
- for i in range(num_sat):
- target_num_points = (i + 1) * N_points
- selected_pixels = circle_2D_filling_TSE(Ny, Nz, Ny_center, Nz_center, target_num_points, N_points, previous_pixels)
- k_space_fill.append(selected_pixels)
- previous_pixels = previous_pixels + selected_pixels
- last_k_space_volume = circle_2D_filling_TSE_last_acq(Ny, Nz, previous_pixels, N_points)
- if last_k_space_volume != None:
- k_space_fill.append(last_k_space_volume)
- if num_sat + 1 == num_echo:
- pass
- else:
- k_space_skip_temp = []
- for i in range( N_points):
- k_space_skip_temp.append(('skip', 'skip'))
- for i in range(num_echo - num_sat - 1):
- k_space_fill.append(k_space_skip_temp)
- eff_TE_reordered = effective_TE_reorder(num_te_eff, num_echo)
- k_space_fill_final = []
- for ii in range(len(k_space_fill[0])):
- one_line = []
- for jj in range(len(k_space_fill)):
- one_line.append(k_space_fill[eff_TE_reordered[jj]][ii])
- k_space_fill_final.append(one_line)
- if dummy:
- k_space_fill_final = k_space_dummy + k_space_fill_final
- return k_space_fill_final
|