# -*- coding: utf-8 -*- """ A subroutine to add IR block. Requires the params structure as input. @author: petrm """ import os import sys # need to add the project dir with the utilities folder to path: project_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) sys.path.append(project_dir) from pypulseq.make_sinc_pulse import make_sinc_pulse from pypulseq.make_trapezoid import make_trapezoid from pypulseq.make_delay import make_delay from pypulseq.calc_duration import calc_duration as calc_dur from math import pi import numpy as np def IR_block(params, hw, IR_geom_offset): # function creates inversion recovery block with delay # ============================================================================= # Get params from GUI # ============================================================================= t_inv = params['t_inv'] t_BW_product_inv = params['t_BW_product_inv'] TI_calc_block = params['TI_calc_block'] if not 'dG' in params: params['dG'] = hw.grad_ramp_time spoiler_area = params['magn_prep_spoiler_area'] if not 'flip_IR' in params: params['flip_IR'] = round(180 * pi / 180, 3) # ============================================================================= # We agreed that IR in 3D is always nonselective. FoV_ss is a 3D indicator # ============================================================================= if 'FoV_ss' in params: slice_selective = False else: slice_selective = True # ============================================================================= # Calculate module # ============================================================================= rf_IR_output = make_sinc_pulse(flip_angle = params['flip_IR'], system = hw, duration = t_inv, slice_thickness = params['inv_thkn'], apodization = 0.5, time_bw_product = round(t_BW_product_inv, 8), freq_offset = 0, phase_offset = 90 * pi / 180, return_gz = slice_selective) if slice_selective: # in this case, rf_IR_output is a list of namespaces rf_IR = rf_IR_output[0] gz_IR = rf_IR_output[1] rf_IR.freq_offset = IR_geom_offset * gz_IR.amplitude # calculate IR freq offset from the geom offset (for slices) duration_IR_object = calc_dur(gz_IR) IR_return_objects_list = [rf_IR, gz_IR] else: # in this case, rf_IR_output is actually rf_IR itself rf_IR = rf_IR_output duration_IR_object = calc_dur(rf_IR) IR_return_objects_list = [rf_IR] # calculate spoiler gz_IR_spoil = make_trapezoid(channel = "z", system = hw, area = spoiler_area, rise_time = params['dG']) duration_gz_IR_spoil = calc_dur(gz_IR_spoil) # calculate delay TI_delay = TI_calc_block - 1/2*duration_IR_object - duration_gz_IR_spoil TI_delay = np.ceil(TI_delay / hw.grad_raster_time) * hw.grad_raster_time delay_IR = make_delay(TI_delay) # calculate duration duration_IR_total = duration_IR_object + duration_gz_IR_spoil + TI_delay return (IR_return_objects_list, [gz_IR_spoil], [delay_IR]), duration_IR_total