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