calc_rf_bandwidth.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from types import SimpleNamespace
  2. from typing import Union, Tuple
  3. import numpy as np
  4. from seqgen.pypulseq.calc_rf_center import calc_rf_center
  5. def calc_rf_bandwidth(
  6. rf: SimpleNamespace,
  7. cutoff: float = 0.5,
  8. return_axis: bool = False,
  9. return_spectrum: bool = False,
  10. ) -> Union[float, Tuple[float, np.ndarray], Tuple[float, np.ndarray, float]]:
  11. """
  12. Calculate the spectrum of the RF pulse. Returns the bandwidth of the pulse (calculated by a simple FFT, e.g.
  13. presuming a low-angle approximation) and optionally the spectrum and the frequency axis. The default for the
  14. optional parameter 'cutoff' is 0.5.
  15. Parameters
  16. ----------
  17. rf : SimpleNamespace
  18. RF pulse event.
  19. cutoff : float, default=0.5
  20. return_axis : bool, default=False
  21. Boolean flag to indicate if frequency axis of RF pulse will be returned.
  22. return_spectrum : bool, default=False
  23. Boolean flag to indicate if spectrum of RF pulse will be returned.
  24. Returns
  25. -------
  26. bw : float
  27. Bandwidth of the RF pulse.
  28. """
  29. time_center, _ = calc_rf_center(rf)
  30. # Resample the pulse to a reasonable time array
  31. dw = 10 # Hz
  32. dt = 1e-6 # For now, 1 MHz
  33. nn = np.round(1 / dw / dt)
  34. tt = np.arange(-np.floor(nn / 2), np.ceil(nn / 2) - 1) * dt
  35. rfs = np.interp(xp=rf.t - time_center, fp=rf.signal, x=tt)
  36. spectrum = np.fft.fftshift(np.fft.fft(np.fft.fftshift(rfs)))
  37. w = np.arange(-np.floor(nn / 2), np.ceil(nn / 2) - 1) * dw
  38. w1 = __find_flank(w, spectrum, cutoff)
  39. w2 = __find_flank(w[::-1], spectrum[::-1], cutoff)
  40. bw = w2 - w1
  41. if return_spectrum and not return_axis:
  42. return bw, spectrum
  43. if return_axis:
  44. return bw, spectrum, w
  45. return bw
  46. def __find_flank(x, f, c):
  47. m = np.max(np.abs(f))
  48. f = np.abs(f) / m
  49. i = np.argwhere(f > c)[0]
  50. return x[i]