# -*- coding: utf-8 -*- """ @author: petrm """ import os import sys import numpy as np # 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 utilities.magn_prep.IR_block import IR_block def create_params_prep_field(params): if params['IR']: params['inv_prep'] = 'IR' return params def magn_prep_calc(params, scanner_parameters, split_dur = False, calc_offsets = True): params = create_params_prep_field(params) prep_calc = () prep_dur = 0 IR_dur = 0 contr_prep_dur = 0 # start with IR IR_calc_list = [] try: # using try because match case for some reason doesn't work functions = { 'IR' : IR_block, # inv_prep functions listed in the dictionary } func = functions.get(params['inv_prep']) # choosing one of them according to params. if calc_offsets: IR_geom_offsets = (np.linspace(0, params['sl_nb']-1, np.int16(params['sl_nb'])) \ - 0.5*(np.double(params['sl_nb'])-1)) \ * (params['sl_thkn']*(100+params['sl_gap'])/100) params['inv_thkn'] = params['sl_thkn'] # selective inversion of the slice else: IR_geom_offsets = [0] if 'FoV_ss' in params: params['inv_thkn'] = params['FoV_ss'] # selective inversion of the whole FoV, e.g. in 3D else: print(' ') print('!!! WARNING !!!') print('Check the parameter of the inversion slab thickness!') print("Using the default value params['inv_thkn'] = 0.45 m") params['inv_thkn'] = 0.45 for IR_geom_offset in IR_geom_offsets: IR_calc, IR_dur = func(params, scanner_parameters, IR_geom_offset) IR_calc_list.append(IR_calc) # list of the IR objects differing only in freq_offsets prep_calc = prep_calc + (IR_calc_list,) prep_dur += IR_dur except: prep_calc = prep_calc + (None,) # NoneType in the first postion == no IR # contr_prep functions: return prep_calc, prep_dur # all calculated objects and timings stored here def magn_prep_add(prep_calc, seq, curr_slice = None, only_one = None): # function to add magn_prep objects. # prep_calc contains all objects calculated in magn_prep_calc # seq is provided from the main code # curr_slice is provided from the main code # only_one can be: # 'inv_prep' – if you need to add only inversion options at the place # where the function is called # 'contr_prep' – if you need only contrast preparations at # the place where the function is called if prep_calc == (None, None): return seq # prep_calc is a tuple where all calculated inv_prep and contr_prep stuff is stored. # The first element of this tuple contains the Standard Inversion objects. It is a list. # The length of this list is defined by the number of inversion slices (= Ex slices in 2D) # If this list has only one element, it means that we have 1 inversion slice # (e.g. a huge inversion slab for 3D) # # Lets choose one piece of inversion data from this list, corresponding to curr_slice: # IR_objects_curr_slice = prep_calc[0][curr_slice] # # This itself is a tuple. # Each element of this tuple is a list of IR objects that we need to add to # the sequence simultaneously, i.e. inversion pulse and inversion gradient. # These elements (blocks) are added in a loop over IR_objects_curr_slice # one after another. if not (prep_calc[0] is None): # if IR was calculated if not (curr_slice is None): # function is called from the slice loop. IR_objects_curr_slice = prep_calc[0][curr_slice] else: # function is called outside the slice loop IR_objects_curr_slice = prep_calc[0][0] for blocks in IR_objects_curr_slice: seq.add_block(*blocks) # add the list-stored blocks of IR objects of the current slice return seq