# -*- coding: utf-8 -*- """ Created on Thu Mar 14 17:26:27 2024 @author: zilya """ import tkinter as tk import numpy as np import json from datetime import datetime from seqgen_TSE_NIRSII import seqgen_TSE_NIRSII from types import SimpleNamespace from utilities.param_constants import param_rf_inv from utilities.param_constants import param_hardware from utilities.param_constants import param_rf_SE from utilities.param_constants import param_default def calc_lims(): # reading params from GUI global param param = SimpleNamespace() param = param_dj_get(M0_dj) # reading hardware constants hw = param_hardware() # calculating limits lim = SimpleNamespace() param.sl_nb = 1 param.sl_thkn = 5e-3 param.sl_gap = 100 param.FoV_p = 256e-3 param.Nf = 128 param.Np = 128 param.BW_pixel = 400 param.ETL = 16 param.concats = 1 param.FA = 90 param.RA = 180 param.average = 1 param.D_scans = 0 param.HASTE = False param.diffusion = False param.Dixon = False param.PI_factor = 1 rf = param_rf_SE(param.sl_thkn) BW_ex_pulse = rf.t_BW_product_ex/rf.t_ex t_exwd = rf.t_ex + 2 *hw.rf_dead_time t_refwd = rf.t_ref + 2 * hw.rf_dead_time # ---- Вычисление основных площадей и длительностей ------ param.dG = 250e-6 A_ex = BW_ex_pulse*(t_exwd+param.dG)/param.sl_thkn A_read = param.Nf/param.FoV_f A_ph = param.Np/2/param.FoV_p A_reph = 0.25*A_ex A_pre = 1.5*A_read A_crs = 0.75*A_ex A_crr = A_read A_sps = 4*A_ex t_reph_min = A_reph/hw.G_amp_max + param.dG t_pre_min = A_pre/hw.G_amp_max + param.dG t_pre_min = max(t_reph_min,t_pre_min) t_pre_min = np.ceil(t_pre_min / hw.grad_raster_time)*hw.grad_raster_time t_crs_min = A_crs/hw.G_amp_max + param.dG t_crr_min = A_crr/hw.G_amp_max + param.dG t_ph_min = A_ph/hw.G_amp_max + param.dG t_cr_min = max(t_crs_min,t_crr_min,t_ph_min) t_cr_min = np.ceil(t_cr_min / hw.grad_raster_time)*hw.grad_raster_time t_read = 1/param.BW_pixel t_read = np.ceil(t_read / hw.grad_raster_time)*hw.grad_raster_time param.BW_pixel = 1/t_read t_sps = A_sps/hw.G_amp_max + hw.tau_max t_sps = np.ceil(t_sps / hw.grad_raster_time)*hw.grad_raster_time ES_1 = t_refwd + t_read + 2*t_cr_min ES_2 = t_refwd + t_exwd + 2*t_cr_min + 2*t_pre_min ES = max(ES_1,ES_2) param.ES = np.ceil(ES/ hw.grad_raster_time)*hw.grad_raster_time t_cr = 0.5*(ES-rf.t_ref-t_read) t_cr = np.ceil(t_cr / hw.grad_raster_time)*hw.grad_raster_time t_pre = 0.5*(ES-rf.t_ref-t_exwd) t_pre = np.ceil(t_pre / hw.grad_raster_time)*hw.grad_raster_time param.TE = param.N_TE*ES lim.N_TE_min = 1 lim.N_TE_max = param.ETL lim.TR_min = ES*(param.ETL) + t_exwd/2 + t_read/2 + t_sps + param.dG + hw.rf_dead_time lim.TR_max = 10 lim.TR_min = np.ceil(lim.TR_min/ hw.grad_raster_time)*hw.grad_raster_time lim.Nf_min = 1 lim.Nf_max = min(param.FoV_f*hw.G_amp_max*(t_read),1600) lim.Np_min = 1 Np_max1 = param.Nf Np_max2 = 2*param.FoV_p*hw.G_amp_max*(t_cr-param.dG) lim.Np_max = min(Np_max1,Np_max2,lim.Nf_max) FoV_min = 25e-3 lim.FoV_f_max = 450e-3 FoV_f_min = param.Nf/(hw.G_amp_max*t_read) lim.FoV_f_min = max(FoV_f_min,FoV_min) lim.TI_min, lim.TI_max = 0, 0 param.magn_prep = "off" if param.IR == True: param.magn_prep = "IR" rf_inv = param_rf_inv() rf = SimpleNamespace(**rf.__dict__, **rf_inv.__dict__) A_sp_inv = 7000 t_sp_inv = A_sp_inv/hw.G_amp_max + param.dG t_sp_inv = np.ceil(t_sp_inv/ hw.grad_raster_time)*hw.grad_raster_time lim.TR_min = rf.t_inv/2 + param.TI + lim.TR_min - rf.t_ex/2 lim.TI_min = rf.t_inv/2 + t_sp_inv + rf.t_ex/2 + 2*param.dG lim.TI_max = param.TR - (rf.t_inv/2 + lim.TR_min - rf.t_ex/2) param.TI_calc_block = param.TI - (rf.t_ex/2 + param.dG) param.magn_prep_spoiler_area = A_sp_inv param.TI_calc_block = np.ceil(param.TI_calc_block/ hw.grad_raster_time)*hw.grad_raster_time lim.concats_min = np.ceil(param.sl_nb/(np.floor(param.TR/lim.TR_min))) lim.concats_max = param.sl_nb # database of params param = SimpleNamespace(**param.__dict__, **hw.__dict__, **rf.__dict__) # showing limits on GUI param_set_lim(M0_dj,lim,param) def save(): param_lists = param_dj_get_lists(M0_dj) array = [] for i_FoV in range((param_lists.FoV_f_N)): for i_N_TE in range((param_lists.N_TE_N)): for i_TR in range((param_lists.TR_N)): for i_TI in range((param_lists.TI_N)): param.FoV_f = param_lists.FoV_f_from + (param_lists.FoV_f_to - param_lists.FoV_f_from)/(param_lists.FoV_f_N+1)* (i_FoV+1) param.N_TE = param_lists.N_TE_from + (param_lists.N_TE_to - param_lists.N_TE_from)/(param_lists.N_TE_N+1)* (i_N_TE+1) param.TR = param_lists.TR_from + (param_lists.TR_to - param_lists.TR_from)/(param_lists.TR_N+1)* (i_TR+1) if param.IR == True: param.TI = param_lists.TI_from + (param_lists.TI_to - param_lists.TI_from)/(param_lists.TI_N+1)* (i_TI+1) param.TI_calc_block = param.TI - (param.t_ex/2 + param.dG) else: param.TI = 0 param.TI_calc_block = 0 param.FoV_f = np.ceil(param.FoV_f*10000)/10000 param.N_TE = np.ceil(param.N_TE) param.TR = np.ceil(param.TR/ param.grad_raster_time)*param.grad_raster_time param.TI = np.ceil(param.TI/ param.grad_raster_time)*param.grad_raster_time param.TI_calc_block = np.ceil(param.TI_calc_block/ param.grad_raster_time)*param.grad_raster_time try: output_folderename = "sequences\\" code = str(i_FoV) + str(i_N_TE) + str(i_TR) + str(i_TI) output_filename = str(M0_dj.textBox_name.get()) + '_' output_sequence, k_space_order_filing = seqgen_TSE_NIRSII(param) output_sequence.plot() output_sequence.write(output_folderename + output_filename + code) file = open(output_folderename + output_filename + code + '.json', 'w') json.dump(param.__dict__, file, indent = 4) file.close() k_space_save = {'k_space_order': k_space_order_filing} kspace_output_filename = output_folderename + output_filename + code + "_k_space_order_filing" with open(kspace_output_filename + ".json", 'w') as outfile: json.dump(k_space_save, outfile) array.append([param.FoV_f, param.N_TE, param.TR, param.TI]) print("work for ", str([param.FoV_f, param.N_TE, param.TR, param.TI])) except: print("error for ", str([param.FoV_f, param.N_TE, param.TR, param.TI])) def param_digits_create(Main,M0_dj, default): row = 0 M0_dj.label_min = tk.Label(Main, text = "min", width = 10) M0_dj.label_min.grid(row=row, column=2) M0_dj.label_max = tk.Label(Main, text = "max", width = 10) M0_dj.label_max.grid(row=row, column=3) M0_dj.label_min = tk.Label(Main, text = "from", width = 10) M0_dj.label_min.grid(row=row, column=4) M0_dj.label_max = tk.Label(Main, text = "to", width = 10) M0_dj.label_max.grid(row=row, column=5) M0_dj.label_max = tk.Label(Main, text = "N", width = 10) M0_dj.label_max.grid(row=row, column=6) row += 1 M0_dj.label_FoV_f = tk.Label(Main, text = 'FoV_f, m') M0_dj.label_FoV_f.grid(row=row , column=0,sticky = "E") M0_dj.textBox_FoV_f = tk.Entry(Main,width = 6) M0_dj.textBox_FoV_f.insert(0, default.FoV_f) M0_dj.textBox_FoV_f.grid(row=row, column=1) M0_dj.label_FoV_f_min = tk.Label(Main) M0_dj.label_FoV_f_min.grid(row=row, column=2) M0_dj.label_FoV_f_max = tk.Label(Main) M0_dj.label_FoV_f_max.grid(row=row, column=3) M0_dj.textBox_FoV_f_from = tk.Entry(Main,width = 6) M0_dj.textBox_FoV_f_from.insert(0, default.FoV_f) M0_dj.textBox_FoV_f_from.grid(row=row, column=4) M0_dj.textBox_FoV_f_to = tk.Entry(Main,width = 6) M0_dj.textBox_FoV_f_to.insert(0, default.FoV_f) M0_dj.textBox_FoV_f_to.grid(row=row, column=5) M0_dj.textBox_FoV_f_N = tk.Entry(Main,width = 6) M0_dj.textBox_FoV_f_N.insert(0, 1) M0_dj.textBox_FoV_f_N.grid(row=row, column=6) row += 1 M0_dj.label_N_TE = tk.Label(Main, text = 'N_TE') M0_dj.label_N_TE.grid(row=row , column=0,sticky = "E") M0_dj.textBox_N_TE = tk.Entry(Main,width = 6) M0_dj.textBox_N_TE.insert(0, default.N_TE) M0_dj.textBox_N_TE.grid(row=row, column=1) M0_dj.label_N_TE_min = tk.Label(Main) M0_dj.label_N_TE_min.grid(row=row, column=2) M0_dj.label_N_TE_max = tk.Label(Main) M0_dj.label_N_TE_max.grid(row=row, column=3) M0_dj.textBox_N_TE_from = tk.Entry(Main,width = 6) M0_dj.textBox_N_TE_from.insert(0, default.N_TE) M0_dj.textBox_N_TE_from.grid(row=row, column=4) M0_dj.textBox_N_TE_to = tk.Entry(Main,width = 6) M0_dj.textBox_N_TE_to.insert(0, default.N_TE) M0_dj.textBox_N_TE_to.grid(row=row, column=5) M0_dj.textBox_N_TE_N = tk.Entry(Main,width = 6) M0_dj.textBox_N_TE_N.insert(0, 1) M0_dj.textBox_N_TE_N.grid(row=row, column=6) row += 1 M0_dj.label_TE = tk.Label(Main, text = 'TE, c') M0_dj.label_TE.grid(row=row , column=0,sticky = "E") M0_dj.label_TE_v = tk.Label(Main) M0_dj.label_TE_v.grid(row=row, column=1) row += 1 M0_dj.label_TR = tk.Label(Main, text = 'TR, s') M0_dj.label_TR.grid(row=row, column=0,sticky = "E") M0_dj.textBox_TR = tk.Entry(Main,width = 6) M0_dj.textBox_TR.insert(0, default.TR) M0_dj.textBox_TR.grid(row=row, column=1) M0_dj.label_TR_min = tk.Label(Main) M0_dj.label_TR_min.grid(row=row, column=2) M0_dj.label_TR_max = tk.Label(Main) M0_dj.label_TR_max.grid(row=row, column=3) M0_dj.textBox_TR_from = tk.Entry(Main,width = 6) M0_dj.textBox_TR_from.insert(0, default.TR) M0_dj.textBox_TR_from.grid(row=row, column=4) M0_dj.textBox_TR_to = tk.Entry(Main,width = 6) M0_dj.textBox_TR_to.insert(0, default.TR) M0_dj.textBox_TR_to.grid(row=row, column=5) M0_dj.textBox_TR_N = tk.Entry(Main,width = 6) M0_dj.textBox_TR_N.insert(0, 1) M0_dj.textBox_TR_N.grid(row=row, column=6) row += 1 M0_dj.label_ETL = tk.Label(Main, text = 'ETL') M0_dj.label_ETL.grid(row=row , column=0,sticky = "E") M0_dj.label_ETL_v = tk.Label(Main) M0_dj.label_ETL_v.grid(row=row, column=1) row += 1 M0_dj.radio_IR = tk.IntVar() M0_dj.radio_IR.set(20) M0_dj.labelIR = tk.Label(Main, text = "IR:", width = 10) M0_dj.labelIR.grid(row=row, column=0,sticky = "E") M0_dj.IR_off = tk.Radiobutton(Main, text="off", variable=M0_dj.radio_IR, value=0) M0_dj.IR_off.grid(row=row, column=1) M0_dj.IR_on = tk.Radiobutton(Main, text="on", variable=M0_dj.radio_IR, value=1) M0_dj.IR_on.grid(row=row, column=2) row += 1 M0_dj.label_TI = tk.Label(Main, text = 'TI, s') M0_dj.label_TI.grid(row=row, column=0,sticky = "E") M0_dj.textBox_TI = tk.Entry(Main,width = 6) M0_dj.textBox_TI.insert(0, default.TI) M0_dj.textBox_TI.grid(row=row, column=1) M0_dj.label_TI_min = tk.Label(Main) M0_dj.label_TI_min.grid(row=row, column=2) M0_dj.label_TI_max = tk.Label(Main) M0_dj.label_TI_max.grid(row=row, column=3) M0_dj.textBox_TI_from = tk.Entry(Main,width = 6) M0_dj.textBox_TI_from.insert(0, default.TI) M0_dj.textBox_TI_from.grid(row=row, column=4) M0_dj.textBox_TI_to = tk.Entry(Main,width = 6) M0_dj.textBox_TI_to.insert(0, default.TI) M0_dj.textBox_TI_to.grid(row=row, column=5) M0_dj.textBox_TI_N = tk.Entry(Main,width = 6) M0_dj.textBox_TI_N.insert(0, 1) M0_dj.textBox_TI_N.grid(row=row, column=6) row += 1 def param_set_lim(M0_dj,lim,param): M0_dj.label_FoV_f_min.configure(text = str(np.ceil(lim.FoV_f_min*1000)/1000)) M0_dj.label_FoV_f_max.configure(text = str(np.floor(lim.FoV_f_max*1000)/1000)) M0_dj.label_N_TE_min.configure(text = str(np.ceil(lim.N_TE_min))) M0_dj.label_N_TE_max.configure(text = str(np.floor(lim.N_TE_max))) M0_dj.label_TE_v.configure(text = str(np.floor(param.TE*1000)/1000)) M0_dj.label_TR_min.configure(text = str(np.ceil(lim.TR_min*1000)/1000)) M0_dj.label_TR_max.configure(text = str(np.floor(lim.TR_max*1000)/1000)) M0_dj.label_ETL_v.configure(text = str(np.floor(param.ETL))) M0_dj.label_TI_min.configure(text = str(np.ceil(lim.TI_min*1000)/1000)) M0_dj.label_TI_max.configure(text = str(np.floor(lim.TI_max*1000)/1000)) def param_dj_get(M0_dj): param_get = SimpleNamespace() param_get.FoV_f = float(M0_dj.textBox_FoV_f.get()) param_get.N_TE = float(M0_dj.textBox_N_TE.get()) param_get.TR = float(M0_dj.textBox_TR.get()) if M0_dj.radio_IR.get() == 1: param_get.IR = True else: param_get.IR = False param_get.TI = float(M0_dj.textBox_TI.get()) return param_get def param_dj_get_lists(M0_dj): param_lists = SimpleNamespace() param_lists.FoV_f_from = float(M0_dj.textBox_FoV_f_from.get()) param_lists.FoV_f_to = float(M0_dj.textBox_FoV_f_to.get()) param_lists.FoV_f_N = int(M0_dj.textBox_FoV_f_N.get()) param_lists.N_TE_from = float(M0_dj.textBox_N_TE_from.get()) param_lists.N_TE_to = float(M0_dj.textBox_N_TE_to.get()) param_lists.N_TE_N = int(M0_dj.textBox_N_TE_N.get()) param_lists.TR_from = float(M0_dj.textBox_TR_from.get()) param_lists.TR_to = float(M0_dj.textBox_TR_to.get()) param_lists.TR_N = int(M0_dj.textBox_TR_N.get()) param_lists.TI_from = float(M0_dj.textBox_TI_from.get()) param_lists.TI_to = float(M0_dj.textBox_TI_to.get()) param_lists.TI_N = int(M0_dj.textBox_TI_N.get()) return param_lists name = "TSE" default = param_default() default.FoV_f = 256e-3 default.N_TE = 1 default.TR = 3500e-3 default.TI = 100e-3 Main = tk.Tk() Main.title(name) Main.geometry("700x300+300+300") Main.resizable(False,False) M0_dj = SimpleNamespace() param_digits_create(Main,M0_dj,default) M0_dj.btn_set = tk.Button(Main, text = 'Set',command = calc_lims) M0_dj.btn_set.grid(row=1, column=8,sticky = "W") M0_dj.btn_save = tk.Button(Main, text = 'Save', command = save) M0_dj.btn_save.grid(row=4, column=8,sticky = "W") # filename M0_dj.label_name= tk.Label(Main, text = 'Output file name',width = 13) M0_dj.label_name.grid(row=5, column=8,sticky = "W") M0_dj.textBox_name = tk.Entry(Main,width = 25) M0_dj.textBox_name.insert(0, name + datetime.now().strftime("_%d%m%y_%H%M")) M0_dj.textBox_name.grid(row=6, column=8, columnspan=3,sticky = "W") calc_lims() Main.mainloop() # Main.mainloop()