| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- # -*- 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
|