opts.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. from seqgen.pypulseq.convert import convert
  2. class Opts:
  3. """
  4. System limits of an MR scanner.
  5. Attributes
  6. ----------
  7. adc_dead_time : float, default=0
  8. Dead time for ADC readout pulses.
  9. gamma : float, default=42.576e6
  10. Gyromagnetic ratio. Default gamma is specified for Hydrogen.
  11. grad_raster_time : float, default=10e-6
  12. Raster time for gradient waveforms.
  13. grad_unit : str, default='Hz/m'
  14. Unit of maximum gradient amplitude. Must be one of 'Hz/m', 'mT/m' or 'rad/ms/mm'.
  15. max_grad : float, default=0
  16. Maximum gradient amplitude.
  17. max_slew : float, default=0
  18. Maximum slew rate.
  19. rf_dead_time : float, default=0
  20. Dead time for radio-frequency pulses.
  21. rf_raster_time : float, default=1e-6
  22. Raster time for radio-frequency pulses.
  23. rf_ringdown_time : float, default=0
  24. Ringdown time for radio-frequency pulses.
  25. rise_time : float, default=0
  26. Rise time for gradients.
  27. slew_unit : str, default='Hz/m/s'
  28. Unit of maximum slew rate. Must be one of 'Hz/m/s', 'mT/m/ms', 'T/m/s' or 'rad/ms/mm/ms'.
  29. Raises
  30. ------
  31. ValueError
  32. If invalid `grad_unit` is passed. Must be one of 'Hz/m', 'mT/m' or 'rad/ms/mm'.
  33. If invalid `slew_unit` is passed. Must be one of 'Hz/m/s', 'mT/m/ms', 'T/m/s' or 'rad/ms/mm/ms'.
  34. """
  35. def __init__(
  36. self,
  37. adc_dead_time: float = 0,
  38. adc_raster_time: float = 100e-9,
  39. block_duration_raster: float = 10e-6,
  40. gamma: float = 42.576e6,
  41. grad_raster_time: float = 10e-6,
  42. grad_unit: str = "Hz/m",
  43. max_grad: float = 0,
  44. max_slew: float = 0,
  45. rf_dead_time: float = 0,
  46. rf_raster_time: float = 1e-6,
  47. rf_ringdown_time: float = 0,
  48. rise_time: float = 0,
  49. slew_unit: str = "Hz/m/s",
  50. B0: float = 1.5,
  51. ):
  52. valid_grad_units = ["Hz/m", "mT/m", "rad/ms/mm"]
  53. valid_slew_units = ["Hz/m/s", "mT/m/ms", "T/m/s", "rad/ms/mm/ms"]
  54. if grad_unit not in valid_grad_units:
  55. raise ValueError(
  56. f"Invalid gradient unit. Must be one of 'Hz/m', 'mT/m' or 'rad/ms/mm'. "
  57. f"Passed: {grad_unit}"
  58. )
  59. if slew_unit not in valid_slew_units:
  60. raise ValueError(
  61. f"Invalid slew rate unit. Must be one of 'Hz/m/s', 'mT/m/ms', 'T/m/s' or 'rad/ms/mm/ms'. "
  62. f"Passed: {slew_unit}"
  63. )
  64. if max_grad == 0:
  65. max_grad = convert(from_value=40, from_unit="mT/m", gamma=gamma)
  66. else:
  67. max_grad = convert(
  68. from_value=max_grad, from_unit=grad_unit, to_unit="Hz/m", gamma=gamma
  69. )
  70. if max_slew == 0:
  71. max_slew = convert(from_value=170, from_unit="T/m/s", gamma=gamma)
  72. else:
  73. max_slew = convert(
  74. from_value=max_slew, from_unit=slew_unit, to_unit="Hz/m", gamma=gamma
  75. )
  76. if rise_time != 0:
  77. max_slew = max_grad / rise_time
  78. self.max_grad = max_grad
  79. self.max_slew = max_slew
  80. self.rise_time = rise_time
  81. self.rf_dead_time = rf_dead_time
  82. self.rf_ringdown_time = rf_ringdown_time
  83. self.adc_dead_time = adc_dead_time
  84. self.adc_raster_time = adc_raster_time
  85. self.rf_raster_time = rf_raster_time
  86. self.grad_raster_time = grad_raster_time
  87. self.block_duration_raster = block_duration_raster
  88. self.gamma = gamma
  89. self.B0 = B0
  90. def __str__(self) -> str:
  91. """
  92. Print a string representation of the system limits objects.
  93. """
  94. variables = vars(self)
  95. s = [f"{key}: {value}" for key, value in variables.items()]
  96. s = "\n".join(s)
  97. s = "System limits:\n" + s
  98. return s