magn_prep.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # -*- coding: utf-8 -*-
  2. """
  3. @author: petrm
  4. """
  5. import os
  6. import sys
  7. import numpy as np
  8. # need to add the project dir with the utilities folder to path:
  9. project_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
  10. sys.path.append(project_dir)
  11. from utilities.magn_prep.IR_block import IR_block
  12. def create_params_prep_field(params):
  13. if params['IR']:
  14. params['inv_prep'] = 'IR'
  15. return params
  16. def magn_prep_calc(params, scanner_parameters, split_dur = False, calc_offsets = True):
  17. params = create_params_prep_field(params)
  18. prep_calc = ()
  19. prep_dur = 0
  20. IR_dur = 0
  21. contr_prep_dur = 0
  22. # start with IR
  23. IR_calc_list = []
  24. try: # using try because match case for some reason doesn't work
  25. functions = {
  26. 'IR' : IR_block, # inv_prep functions listed in the dictionary
  27. }
  28. func = functions.get(params['inv_prep']) # choosing one of them according to params.
  29. if calc_offsets:
  30. IR_geom_offsets = (np.linspace(0, params['sl_nb']-1, np.int16(params['sl_nb'])) \
  31. - 0.5*(np.double(params['sl_nb'])-1)) \
  32. * (params['sl_thkn']*(100+params['sl_gap'])/100)
  33. params['inv_thkn'] = params['sl_thkn'] # selective inversion of the slice
  34. else:
  35. IR_geom_offsets = [0]
  36. if 'FoV_ss' in params:
  37. params['inv_thkn'] = params['FoV_ss'] # selective inversion of the whole FoV, e.g. in 3D
  38. else:
  39. print(' ')
  40. print('!!! WARNING !!!')
  41. print('Check the parameter of the inversion slab thickness!')
  42. print("Using the default value params['inv_thkn'] = 0.45 m")
  43. params['inv_thkn'] = 0.45
  44. for IR_geom_offset in IR_geom_offsets:
  45. IR_calc, IR_dur = func(params, scanner_parameters, IR_geom_offset)
  46. IR_calc_list.append(IR_calc) # list of the IR objects differing only in freq_offsets
  47. prep_calc = prep_calc + (IR_calc_list,)
  48. prep_dur += IR_dur
  49. except:
  50. prep_calc = prep_calc + (None,) # NoneType in the first postion == no IR
  51. # contr_prep functions:
  52. return prep_calc, prep_dur # all calculated objects and timings stored here
  53. def magn_prep_add(prep_calc, seq, curr_slice = None, only_one = None):
  54. # function to add magn_prep objects.
  55. # prep_calc contains all objects calculated in magn_prep_calc
  56. # seq is provided from the main code
  57. # curr_slice is provided from the main code
  58. # only_one can be:
  59. # 'inv_prep' – if you need to add only inversion options at the place
  60. # where the function is called
  61. # 'contr_prep' – if you need only contrast preparations at
  62. # the place where the function is called
  63. if prep_calc == (None, None):
  64. return seq
  65. # prep_calc is a tuple where all calculated inv_prep and contr_prep stuff is stored.
  66. # The first element of this tuple contains the Standard Inversion objects. It is a list.
  67. # The length of this list is defined by the number of inversion slices (= Ex slices in 2D)
  68. # If this list has only one element, it means that we have 1 inversion slice
  69. # (e.g. a huge inversion slab for 3D)
  70. #
  71. # Lets choose one piece of inversion data from this list, corresponding to curr_slice:
  72. # IR_objects_curr_slice = prep_calc[0][curr_slice]
  73. #
  74. # This itself is a tuple.
  75. # Each element of this tuple is a list of IR objects that we need to add to
  76. # the sequence simultaneously, i.e. inversion pulse and inversion gradient.
  77. # These elements (blocks) are added in a loop over IR_objects_curr_slice
  78. # one after another.
  79. if not (prep_calc[0] is None): # if IR was calculated
  80. if not (curr_slice is None):
  81. # function is called from the slice loop.
  82. IR_objects_curr_slice = prep_calc[0][curr_slice]
  83. else:
  84. # function is called outside the slice loop
  85. IR_objects_curr_slice = prep_calc[0][0]
  86. for blocks in IR_objects_curr_slice:
  87. seq.add_block(*blocks) # add the list-stored blocks of IR objects of the current slice
  88. return seq