seqgen_STEAM.py 4.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Fri Apr 5 10:43:09 2024
  4. @author: zilya
  5. """
  6. import numpy as np
  7. from LF_scanner.pypulseq.Sequence.sequence import Sequence
  8. from LF_scanner.pypulseq.calc_duration import calc_duration
  9. from LF_scanner.pypulseq.check_timing import check_timing
  10. from LF_scanner.pypulseq.make_adc import make_adc
  11. from LF_scanner.pypulseq.make_delay import make_delay
  12. from LF_scanner.pypulseq.make_sinc_pulse import make_sinc_pulse
  13. from LF_scanner.pypulseq.make_trapezoid import make_trapezoid
  14. from LF_scanner.pypulseq.opts import Opts
  15. def seqgen_STEAM(param):
  16. # Read scanner parameters from the params structure
  17. scanner_parameters = Opts(max_grad = param.G_amp_max, grad_unit = 'Hz/m',\
  18. max_slew = param.G_slew_max, slew_unit = 'Hz/m/s',\
  19. grad_raster_time = param.grad_raster_time,\
  20. rf_raster_time = param.rf_raster_time,\
  21. adc_raster_time = 1/(param.BW_per_point*param.N_point),\
  22. block_duration_raster = max(param.grad_raster_time,param.rf_raster_time))
  23. # For all modules
  24. gradient_ramp_time = param.grad_raster_time*np.ceil((scanner_parameters.max_grad/scanner_parameters.max_slew)/param.grad_raster_time)
  25. # Calculate slice-selection gradient
  26. pulse_bandwidth = np.double(param.t_BW_product_ex) / np.double(param.t_ex) #In Hz
  27. gradient_voxel_amp = np.double(pulse_bandwidth) / np.double(param.voxel_thkn) #In Hz/m
  28. gradient_voxel = make_trapezoid(channel = 'z',
  29. flat_time = np.double(param.t_ex),
  30. rise_time = gradient_ramp_time,
  31. amplitude = gradient_voxel_amp,
  32. system = scanner_parameters)
  33. # Generate the RF pulse
  34. exc_pulse = make_sinc_pulse(flip_angle = np.radians(param.FA),\
  35. duration = np.double(param.t_ex),\
  36. phase_offset = 0,\
  37. time_bw_product = param.t_BW_product_ex,\
  38. delay = gradient_ramp_time,\
  39. system = scanner_parameters)
  40. # Generate the ADC event
  41. adc_module = make_adc(num_samples = param.N_point, duration = 0.5/param.BW_per_point, delay = gradient_ramp_time, system = scanner_parameters)
  42. # Calculate the TE pause time
  43. tau_delay1 = param.tau1 - calc_duration(gradient_voxel)
  44. tau_delay1 = param.grad_raster_time*np.floor(tau_delay1/param.grad_raster_time)
  45. tau_delay2 = param.tau2 - calc_duration(gradient_voxel)
  46. tau_delay2 = param.grad_raster_time*np.floor(tau_delay2/param.grad_raster_time)
  47. tau_delay3 = param.tau1 - 0.5*calc_duration(gradient_voxel)
  48. tau_delay3 = param.grad_raster_time*np.floor(tau_delay3/param.grad_raster_time)
  49. tau_delay1 = make_delay(tau_delay1) if tau_delay1 > 0 else None
  50. tau_delay2 = make_delay(tau_delay2) if tau_delay2 > 0 else None
  51. tau_delay3 = make_delay(tau_delay3) if tau_delay3 > 0 else None
  52. # Calculate the TR fillers
  53. tr_delay = param.TR - (2*param.tau1 + param.tau2 + calc_duration(adc_module) + 0.5*calc_duration(gradient_voxel))
  54. tr_delay = param.grad_raster_time*np.floor(tr_delay/param.grad_raster_time)
  55. tr_delay = make_delay(tr_delay) if tr_delay > 0 else None
  56. seq = Sequence(system = scanner_parameters)
  57. phase_shift = 0
  58. # Dummy scans
  59. for n in range(int(param.average)):
  60. gradient_voxel.channel = 'z'
  61. seq.add_block(exc_pulse,gradient_voxel)
  62. if tau_delay1 is not None:
  63. seq.add_block(tau_delay1)
  64. gradient_voxel.channel = 'y'
  65. seq.add_block(exc_pulse,gradient_voxel)
  66. if tau_delay2 is not None:
  67. seq.add_block(tau_delay2)
  68. gradient_voxel.channel = 'x'
  69. seq.add_block(exc_pulse,gradient_voxel)
  70. if tau_delay3 is not None:
  71. seq.add_block(tau_delay3)
  72. seq.add_block(adc_module)
  73. if tr_delay is not None:
  74. seq.add_block(tr_delay)
  75. print(check_timing(seq))
  76. return seq